ModuleManager.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. namespace Tools;
  3. /**
  4. * Container all modules.
  5. * Allow module managment
  6. **/
  7. class ModuleManager
  8. {
  9. /**
  10. * @var \Tools\Context $context
  11. * /core/tools/Context.php
  12. * Contains website's informations
  13. **/
  14. private $context;
  15. /**
  16. * @var array(\Tool\AModule) $modules
  17. * /core/tools/AModule.php
  18. * Contains all loaded modules
  19. * Can be accessed read-only via $instance->modules
  20. **/
  21. private $modules = array();
  22. /**
  23. * @var boolean $installing true if a module is currently installing
  24. **/
  25. private static $installing = false;
  26. /**
  27. * @var _id_{ID}
  28. * Get the module identified with id ID
  29. * ex: $context->moduleManager->_id_2 will return module with id 2
  30. **/
  31. /**
  32. * @param \Tool\Context $context
  33. * Load all active modules from database.
  34. * Enable hooks for these modules
  35. * Disable them if the module cannot be loaded
  36. **/
  37. public function __construct(&$context)
  38. {
  39. $this->context = $context;
  40. $modulesRoot = $context->router->modulesPath;
  41. $modules = \Entity\Module::getActivated();
  42. $ids = array();
  43. foreach ($modules as $i)
  44. {
  45. $modulePath = "{$modulesRoot}{$i->directory}/main.php";
  46. if (file_exists($modulePath) && $this->loadModule($modulePath, $i))
  47. {
  48. $ids[] = $i->id;
  49. }
  50. else
  51. {
  52. $i->active = false;
  53. $i->save();
  54. }
  55. }
  56. $context->hookManager->loadHooks(\Entity\ModuleHook::getModules($ids));
  57. }
  58. /**
  59. * @param string $path
  60. * @return \Tools\AModule loaded module (or false on error)
  61. **/
  62. private function loadModuleFile($path)
  63. {
  64. $mod = include_once($path);
  65. if (!$mod || !($mod instanceof \Tools\AModule))
  66. return false;
  67. $mod->setContext($this->context);
  68. return $mod;
  69. }
  70. /**
  71. * @param string $path path to module's main file
  72. * @param \Entity\Module $module module's database object to load
  73. * /core/models/Module.php
  74. * @return TRUE on success
  75. * Will try to load module located at $path.
  76. * This function will include the main.php file located in the module's directory
  77. * The file MUST return an AModule object to be considered as successfull
  78. * /core/tools/AModule.php
  79. **/
  80. private function loadModule($path, $module)
  81. {
  82. $mod = $this->loadModuleFile($path);
  83. if ($mod === false)
  84. return false;
  85. $mod->setEntity($module);
  86. $this->modules[] = $mod;
  87. return true;
  88. }
  89. /**
  90. * @param string $modulename
  91. * @return \tools\AModule|false on failure
  92. * Install the module located in {modulePath}/modulename/modulename.php
  93. **/
  94. public function install($modulename)
  95. {
  96. $entity = new \Entity\Module();
  97. $entity->name = $modulename;
  98. $entity->directory = $modulename;
  99. $entity->active = true;
  100. $module = $this->loadModuleFile($this->context->router->modulesPath.$modulename.'/main.php');
  101. if ($module === false)
  102. return false;
  103. $entity->name = $module->getName();
  104. $entity->description = $module->getDescription();
  105. $entity->save();
  106. $module->setEntity($entity);
  107. self::$installing = true;
  108. if ($module->install() == false)
  109. {
  110. self::$installing = false;
  111. $hooks = \Entity\ModuleHook::getModules($entity->id);
  112. foreach ($hooks as $i)
  113. $i->delete();
  114. $entity->delete();
  115. return false;
  116. }
  117. self::$installing = false;
  118. return $module;
  119. }
  120. /*
  121. * TODO revoir tout
  122. * @return array(AModule)
  123. * Will load every modules, and return them.
  124. **/
  125. public function listAvailableModules()
  126. {
  127. $modulesRoot = $context->router->modulesPath;
  128. $result = array();
  129. $modules = scandir($modulesRoot, SCANDIR_SORT_NONE);
  130. foreach ($modules as $i)
  131. {
  132. $path = $modulesRoot.$i;
  133. if ($i == '.' || $i == '..' || !is_dir($path))
  134. continue;
  135. $this->loadModule($path);
  136. }
  137. }
  138. /**
  139. * @param int $id
  140. * @return AModule on success, FALSE on failure (no such ID / module not loaded)
  141. * Get the module identified with id ID
  142. **/
  143. public function getModuleFromId($id)
  144. {
  145. foreach ($this->modules as $i)
  146. {
  147. if ($i->entity->id == $id)
  148. return $i;
  149. }
  150. return FALSE;
  151. }
  152. /**
  153. * @return true if a module is currently installing
  154. **/
  155. public static function isInstalling()
  156. { return self::$installing; }
  157. /**
  158. * Getter
  159. **/
  160. public function __get($key)
  161. {
  162. switch ($key)
  163. {
  164. case "modules":
  165. return $this->modules; break;
  166. }
  167. if (substr($key, 0, 4) == "_id_")
  168. return $this->getModuleFromId((int) substr($key, 4));
  169. throw new \Exception("Cannot access attribute {$key}");
  170. }
  171. }