21 $this->class_script = array();
22 $this->class_childs = array();
23 $this->executed =
false;
24 $this->ini = $a_ini_file;
29 $this->ini = $a_ini_file;
39 $this->ini->setVariable(
"db",
"structure_reload",
"1");
41 if ($this->ini->readVariable(
"db",
"structure_reload") !=
"1") {
42 echo
"Error Cannot write client.ini.file.";
60 if (!$a_force && $this->ini->readVariable(
"db",
"structure_reload") !=
"1") {
65 if ($this->executed) {
72 $this->comp_prefix = $a_comp_prefix;
75 $this->plugin_path = $a_plugin_path;
77 if ($this->plugin_path !=
"" && $this->comp_prefix !=
"") {
78 $this->read_plugins =
true;
86 $this->
storeToDB($ctrl_structure, $a_dir);
89 $this->executed =
true;
91 $this->ini->setVariable(
"db",
"structure_reload",
"0");
99 ilGlobalCache::flushAll();
105 if (!@is_dir($a_cdir)) {
106 throw new \LogicException(
"'$a_cdir' is not a directory.");
109 foreach ($this->getFilesIn($a_cdir) as list($file, $full_path)) {
110 if (!$this->isInterestingFile($file)) {
114 $content = file_get_contents($full_path);
116 $cs = $this->parseFileTo($cs, $full_path, $content);
117 }
catch (\LogicException
$e) {
118 throw new \LogicException(
"In file \"$full_path\": " .
$e->getMessage(),
$e->getCode(),
$e);
120 if (!isset(
$e->class) || !isset(
$e->file_path)) {
123 $this->panicOnDuplicateClass(
141 foreach (scandir($dir) as
$e) {
142 if (
$e ==
"." ||
$e ==
"..") {
145 $f = $this->normalizePath(
"$dir/$e");
147 if (!$this->shouldDescendToDirectory($dir)) {
150 foreach ($this->getFilesIn(
$f) as $s) {
162 $il_absolute_path = $this->getILIASAbsolutePath();
163 $data_dir = $this->normalizePath($il_absolute_path .
"/data");
164 $customizing_dir = $this->normalizePath($il_absolute_path .
"/Customizing");
166 $dir = $this->normalizePath($dir);
167 if ($this->read_plugins) {
168 return $dir != $data_dir;
170 return $dir != $customizing_dir && $dir != $data_dir;
175 return realpath(str_replace([
'//'], [
'/'], $path));
178 const INTERESTING_FILES_REGEXP =
"~^(class\..*\.php)$~i";
182 return preg_match(self::INTERESTING_FILES_REGEXP, $file);
192 $ilDB = $this->getDB();
195 $ilDB->manipulate(
"DELETE FROM ctrl_classfile WHERE comp_prefix = " .
196 $ilDB->quote($this->comp_prefix,
"text"));
197 if ($this->comp_prefix ==
"") {
198 $ilDB->manipulate($q =
"DELETE FROM ctrl_classfile WHERE " .
199 $ilDB->equals(
"comp_prefix",
"",
"text",
true));
203 $ilDB->manipulate(
"DELETE FROM ctrl_calls WHERE comp_prefix = " .
204 $ilDB->quote($this->comp_prefix,
"text"));
205 if ($this->comp_prefix ==
"") {
206 $ilDB->manipulate(
"DELETE FROM ctrl_calls WHERE comp_prefix IS NULL");
209 $msg = implode(
"\n", [
210 "Error: Duplicate call structure definition found (Class %s) in files:",
214 "Please remove the file, that does not belong to the official ILIAS distribution.",
215 "After that invoke 'Tools' -> 'Reload Control Structure' in the ILIAS Setup."
218 throw new \Exception(
230 $ilDB = $this->getDB();
233 $ilDB->manipulate(
"DELETE FROM ctrl_classfile WHERE comp_prefix = " .
234 $ilDB->quote($this->comp_prefix,
"text"));
235 if ($this->comp_prefix ==
"") {
236 $ilDB->manipulate($q =
"DELETE FROM ctrl_classfile WHERE " .
237 $ilDB->equals(
"comp_prefix",
"",
"text",
true));
241 $ilDB->manipulate(
"DELETE FROM ctrl_calls WHERE comp_prefix = " .
242 $ilDB->quote($this->comp_prefix,
"text"));
243 if ($this->comp_prefix ==
"") {
244 $ilDB->manipulate(
"DELETE FROM ctrl_calls WHERE " .
245 $ilDB->equals(
"comp_prefix",
"",
"text",
true));
249 $file = substr(realpath($script), strlen(realpath($start_dir)) + 1);
251 $ilDB->manipulate(sprintf(
252 "INSERT IGNORE INTO ctrl_classfile (class, filename, comp_prefix, plugin_path) " .
253 " VALUES (%s,%s,%s,%s)",
254 $ilDB->quote($class,
"text"),
255 $ilDB->quote($file,
"text"),
256 $ilDB->quote($this->comp_prefix,
"text"),
257 $ilDB->quote($this->plugin_path,
"text")
262 if (!strlen($parent)) {
265 foreach ($children as $child) {
266 if (!strlen(trim($child))) {
270 $ilDB->manipulate(sprintf(
271 "INSERT IGNORE INTO ctrl_calls (parent, child, comp_prefix) " .
273 $ilDB->quote($parent,
"text"),
274 $ilDB->quote($child,
"text"),
275 $ilDB->quote($this->comp_prefix,
"text")
283 $ilDB = $this->getDB();
286 "UPDATE ctrl_classfile SET " .
287 " cid = " .
$ilDB->quote(
"",
"text")
289 $set =
$ilDB->query(
"SELECT * FROM ctrl_classfile ");
291 while ($rec =
$ilDB->fetchAssoc($set)) {
292 $cid = base_convert((
string) $cnt, 10, 36);
294 "UPDATE ctrl_classfile SET " .
295 " cid = " .
$ilDB->quote($cid,
"text") .
296 " WHERE class = " .
$ilDB->quote($rec[
"class"],
"text")
313 list($parent, $children) = $this->getIlCtrlCalls($content);
318 foreach ($children as $child) {
323 list($child, $parents) = $this->getIlCtrlIsCalledBy($content);
328 foreach ($parents as $parent) {
333 $cl = $this->getGUIClassNameFromClassPath($full_path);
334 if ($cl && $this->containsClassDefinitionFor($cl, $content)) {
345 const GUI_CLASS_FILE_REGEXP =
"~^.*[/\\\\]class\.(.*GUI)\.php$~i";
350 if (preg_match(self::GUI_CLASS_FILE_REGEXP, $path,
$res)) {
351 return strtolower(
$res[1]);
358 $regexp =
"~.*class\s+$class~mi";
359 return preg_match($regexp, $content) != 0;
367 const IL_CTRL_DECLARATION_REGEXP =
'~^.*@{WHICH}\s+([\w\\\\]+)\s*:\s*([\w\\\\]+(\s*,\s*[\w\\\\]+)*)\s*$~mi';
374 return $this->getIlCtrlDeclarations($content,
"ilctrl_calls");
382 return $this->getIlCtrlDeclarations($content,
"ilctrl_iscalledby");
390 $regexp = str_replace(
"{WHICH}", $which, self::IL_CTRL_DECLARATION_REGEXP);
392 if (!preg_match_all($regexp, $content,
$res)) {
396 $class_names = array_unique(
$res[1]);
397 if (count($class_names) != 1) {
398 throw new \LogicException(
399 "Found different class names in ilctrl_calls: " . join(
",", $class_names)
404 foreach (
$res[2] as $ls) {
405 foreach (explode(
",", $ls) as $l) {
406 $declaration[] = strtolower(trim($l));
410 return [strtolower(trim($class_names[0])), $declaration];
420 $clone = clone $this;
427 if (!is_null($this->db)) {
437 if (defined(
"ILIAS_ABSOLUTE_PATH")) {
438 return $this->normalizePath(ILIAS_ABSOLUTE_PATH);
440 return dirname(__FILE__, 5);
An exception for terminatinating execution or to throw for unit testing.
Class ilCtrlStructureReader.
getIlCtrlCalls(string $content)
parseFileTo(\ilCtrlStructure $cs, string $full_path, string $content)
readDirTo(string $a_cdir, \ilCtrlStructure $cs)
panicOnDuplicateClass(string $full_path, string $other_path, string $parent)
isInterestingFile(string $file)
getIlCtrlIsCalledBy(string $content)
normalizePath(string $path)
withDB(\ilDBInterface $db)
readStructure( $a_force=false, $a_dir="", $a_comp_prefix="", $a_plugin_path="")
storeToDB(\ilCtrlStructure $ctrl_structure, string $start_dir)
__construct($a_ini_file=null)
shouldDescendToDirectory(string $dir)
containsClassDefinitionFor(string $class, string $content)
getGUIClassNameFromClassPath(string $path)
getIlCtrlDeclarations(string $content, string $which)
getStructure()
parse code files and store call structure in db
The CtrlStructure knows how GUIs call each other and where the code of the guis is located.
withClassChild(string $parent, string $child)
withClassScript(string $class, string $file_path)
getClassScriptOf(string $class)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
foreach($_POST as $key=> $value) $res