PageRenderTime 39ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/atkmoduletools.inc

https://github.com/ibuildingsnl/ATK
PHP | 629 lines | 479 code | 28 blank | 122 comment | 24 complexity | ff8734f6f9fe3e08047202386a54f44b MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-3.0
  1. <?php
  2. /**
  3. * This file is part of the Achievo ATK distribution.
  4. * Detailed copyright and licensing information can be found
  5. * in the doc/COPYRIGHT and doc/LICENSE files which should be
  6. * included in the distribution.
  7. *
  8. * @package atk
  9. * @subpackage modules
  10. *
  11. * Collection of utility methods for use with modules and nodes.
  12. * @todo Move the global methods to classes
  13. *
  14. * @copyright (c)2000-2004 Ibuildings.nl BV
  15. * @license http://www.achievo.org/atk/licensing ATK Open Source License
  16. *
  17. * @version $Revision: 6139 $
  18. * $Id$
  19. */
  20. /**
  21. * @internal Includes, global definitions etc.
  22. */
  23. /**
  24. * A repository of node instances..
  25. * @access private
  26. * @var Array
  27. */
  28. $GLOBALS['g_nodeRepository'] = array();
  29. /**
  30. * A repository of module instances..
  31. * @access private
  32. * @var Array
  33. */
  34. $GLOBALS['g_moduleRepository'] = array();
  35. /**
  36. * registered node action handlers
  37. * @access private
  38. * @var Array
  39. */
  40. $GLOBALS['g_nodeHandlers'] = array();
  41. /**
  42. * registered node listeners
  43. * @access private
  44. * @var Array
  45. */
  46. $GLOBALS['g_nodeListeners'] = array();
  47. /**
  48. * registered node controllers
  49. * @access private
  50. * @var Array
  51. */
  52. $GLOBALS['g_nodeControllers'] = array();
  53. /**
  54. * Gets the node type of a node string
  55. * @param String $node the node name
  56. * @return String the node type
  57. */
  58. function getNodeType($node)
  59. {
  60. $arr = explode(".", $node);
  61. if (count($arr) == 2) return $arr[1];
  62. else return $node;
  63. }
  64. /**
  65. * Gets the module of the node
  66. * @param String $node the node name
  67. * @return String the node's module
  68. */
  69. function getNodeModule($node)
  70. {
  71. $arr = explode(".", $node);
  72. if (count($arr) == 2) return $arr[0];
  73. else return "";
  74. }
  75. /**
  76. * Get an instance of a node. If an instance doesn't exist, it is created.
  77. * @deprecated Use atkGetNode instead.
  78. * @param String $node The node string
  79. * @param bool $init Initialize the node?
  80. * @param String $cache_id The cache id in the node repository
  81. * @param bool $reset Wether or not to reset the particulair node in the repository
  82. * @return atkNode the created instance
  83. */
  84. function &getNode($node, $init=TRUE, $cache_id="default", $reset=false)
  85. {
  86. return atkGetNode($node, $init, $cache_id, $reset);
  87. }
  88. /**
  89. * Get an instance of a node. If an instance doesn't exist, it is created. Note that nodes
  90. * are cached (unless $reset is true); multiple requests for the same node will return exactly
  91. * the same node object.
  92. *
  93. * @param String $node The node string
  94. * @param bool $init Initialize the node?
  95. * @param String $cache_id The cache id in the node repository
  96. * @param bool $reset Whether or not to reset the particular node in the repository
  97. * @return atkNode the node
  98. */
  99. function &atkGetNode($node, $init=TRUE, $cache_id="default", $reset=false)
  100. {
  101. global $g_nodeRepository;
  102. $node = strtolower($node); // classes / directory names should always be in lower-case
  103. if (!isset($g_nodeRepository[$cache_id][$node])||!is_object($g_nodeRepository[$cache_id][$node]) || $reset)
  104. {
  105. atkdebug("Constructing a new node - $node");
  106. $g_nodeRepository[$cache_id][$node] = &newNode($node, $init);
  107. }
  108. return $g_nodeRepository[$cache_id][$node];
  109. }
  110. /**
  111. * Replace, at runtime, the in-memory instance of a node.
  112. *
  113. * This is useful to replace nodes with mocks for testing purposes.
  114. *
  115. * @param String $nodename The full name of the node (module.nodename)
  116. * @param atkNode $node The node instance to replace the current one
  117. * @param String $cache_id If set, replaces only the instance with a certain
  118. * cache_id
  119. * @return atkNode The current node, useful to restore afterwards. Can be
  120. * NULL.
  121. */
  122. function &atkSetNode($nodename, &$node, $cache_id="default")
  123. {
  124. global $g_nodeRepository;
  125. $nodename = strtolower($nodename); // classes / directory names should always be in lower-case
  126. $org = &$g_nodeRepository[$cache_id][$nodename];
  127. $g_nodeRepository[$cache_id][$nodename] = &$node;
  128. return $org;
  129. }
  130. /**
  131. * Retrieves all the registered atkModules
  132. *
  133. * @return Array with modules
  134. */
  135. function atkGetModules()
  136. {
  137. global $g_modules;
  138. return $g_modules;
  139. }
  140. /**
  141. * Retrieve the atkModule with the given name.
  142. *
  143. * @param String $modname The name of the module
  144. * @return atkModule An instance of the atkModule
  145. */
  146. function &atkGetModule($modname)
  147. {
  148. global $g_moduleRepository;
  149. atkimport("atk.atknode");
  150. if (!isset($g_moduleRepository[$modname])||!is_object($g_moduleRepository[$modname]))
  151. {
  152. atkimport("atk.modules.atkmodule");
  153. $corporate_base = atkconfig("corporate_module_base");
  154. if ($corporate_base!="")
  155. {
  156. atkimport($corporate_base);
  157. }
  158. $filename = moduleDir($modname)."module.inc";
  159. if (file_exists($filename))
  160. {
  161. include_once($filename);
  162. }
  163. else
  164. {
  165. atkdebug("Couldn't find module.inc for module '$modname' in '".moduleDir($modname)."'");
  166. }
  167. atkdebug("Constructing a new module - $modname");
  168. if (class_exists("mod_".$modname))
  169. {
  170. $realmodname = "mod_".$modname;
  171. $mod = new $realmodname($modname);
  172. }
  173. else if (class_exists($modname))
  174. {
  175. atkdebug("Warning: Deprecated use of short modulename '$modname'. Class in module.inc should be renamed to 'mod_$modname'.");
  176. $mod = new $modname();
  177. }
  178. else
  179. {
  180. atkimport("atk.utils.atkclassloader");
  181. $mod = atkClassLoader::invokeFromString(atkconfig("missing_module_handler"), array(array("module"=>$modname)));
  182. if ($mod===false)
  183. {
  184. // Changed by Ivo: This used to construct a dummy module, so
  185. // modules could exist that didn't have a module.inc file.
  186. // We no longer support this (2003-01-11)
  187. $mod = NULL;
  188. atkdebug("Warning: module $modname does not exist");
  189. }
  190. }
  191. $g_moduleRepository[$modname] = $mod;
  192. }
  193. return $g_moduleRepository[$modname];
  194. }
  195. /**
  196. * Retrieve the atkModule with the given name.
  197. *
  198. * @deprecated Use atkGetModule instead.
  199. * @param String $modname The name of the module
  200. * @return atkModule an instance of the atkModule
  201. */
  202. function getModule($modname)
  203. {
  204. return atkGetModule($modname);
  205. }
  206. /**
  207. * Retrieve the full filename containing the given node.
  208. *
  209. * @param String $node The name of the node (nodename or module.nodename)
  210. * @return String The filename
  211. */
  212. function nodeFile($node)
  213. {
  214. global $config_classroot, $config_module_path;
  215. $modules = atkGetModules();
  216. /* module and type */
  217. $module = getNodeModule($node);
  218. $type = getNodeType($node);
  219. $file = "class.$type.inc";
  220. /* filename */
  221. if (empty($module))
  222. {
  223. $file = $config_classroot."class.$type.inc";
  224. }
  225. else
  226. {
  227. if (is_array($modules)&&in_array($module, array_keys($modules)))
  228. {
  229. if (file_exists("{$modules[$module]}/nodes/class.{$type}.inc"))
  230. {
  231. $file = "{$modules[$module]}/nodes/class.{$type}.inc";
  232. }
  233. else
  234. {
  235. $file = "{$modules[$module]}/class.{$type}.inc";
  236. }
  237. }
  238. else
  239. {
  240. atkdebug("Couldn't find node '$node' in module '$module'. Trying default module path.");
  241. $file = $config_module_path."/".$module."/class.$type.inc";
  242. }
  243. }
  244. return $file;
  245. }
  246. /**
  247. * Construct a new node
  248. * @param String $node the node type
  249. * @param bool $init initialize the node?
  250. * @return atkNode new node object
  251. */
  252. function &newNode($node, $init=TRUE)
  253. {
  254. $node = strtolower($node); // classes / directory names should always be in lower-case
  255. $module = getNodeModule($node);
  256. if ($module=="")
  257. {
  258. // No module, use the default instance.
  259. $module_inst = new atkModule();
  260. }
  261. else
  262. {
  263. $module_inst = getModule($module);
  264. }
  265. if (is_object($module_inst))
  266. {
  267. if (method_exists($module_inst,'newNode'))
  268. {
  269. $node = $module_inst->newNode($node);
  270. if ($init && $node != NULL) $node->init();
  271. return $node;
  272. }
  273. else atkerror("Module $module does not have newNode function (does it extend from atkModule?)");
  274. }
  275. else atkerror("Module $module could not be instantiated.");
  276. return NULL;
  277. }
  278. /**
  279. * Checks if a certain node exists.
  280. * @param String $node the node type
  281. * @return bool node exists?
  282. */
  283. function nodeExists($node)
  284. {
  285. static $existence = array();
  286. if (array_key_exists($node, $existence))
  287. return $existence[$node];
  288. $module = getNodeModule($node);
  289. if ($module == "") $module = new atkModule();
  290. else $module = getModule(getNodeModule($node));
  291. $exists = is_object($module) && $module->nodeExists($node);
  292. $existence[$node] = $exists;
  293. atkdebug("Node $node exists? ".($exists ? 'yes' : 'no'));
  294. return $exists;
  295. }
  296. /**
  297. * Return the physical directory of a module..
  298. * @param String name of the module.
  299. * @return String The path to the module.
  300. */
  301. function moduleDir($module)
  302. {
  303. $modules = atkGetModules();
  304. if (isset($modules[$module]))
  305. {
  306. $dir = $modules[$module];
  307. if (substr($dir,-1)!='/') return $dir."/";
  308. return $dir;
  309. }
  310. return "";
  311. }
  312. /**
  313. * Creates an URL to a file within the modules directory
  314. * @param $module the module name
  315. * @param $file the directory/filename
  316. * @return URL to file within modules directory
  317. */
  318. function module_url($module, $file)
  319. {
  320. global $config_module_path;
  321. return "$config_module_path/$module/$file";
  322. }
  323. /**
  324. * Check wether a module is installed
  325. * @param String $module The modulename.
  326. * @return bool True if it is, false otherwise
  327. */
  328. function moduleExists($module)
  329. {
  330. $modules = atkGetModules();
  331. return (is_array($modules)&&in_array($module, array_keys($modules)));
  332. }
  333. /**
  334. * Returns a registered node action handler.
  335. * @deprecated Use atkGetNodeHandler instead
  336. * @param $node the name of the node
  337. * @param $action the node action
  338. * @return handler functionname or object (is_subclass_of atkActionHandler) or
  339. * NULL if no handler exists for the specified action
  340. */
  341. function &getNodeHandler($node, $action)
  342. {
  343. return atkGetNodeHandler($node, $action);
  344. }
  345. /**
  346. * Registers a new node action handler.
  347. * @deprecated Use atkRegisterNodeHandler instead
  348. * @param $node the name of the node (* matches all)
  349. * @param $action the node action
  350. * @param $handler handler functionname or object (is_subclass_of atkActionHandler)
  351. * @return true if there is no known handler
  352. *
  353. * @deprecated
  354. * @see atkRegisterNodeHandler
  355. */
  356. function registerNodeHandler($node, $action, &$handler)
  357. {
  358. return atkRegisterNodeHandler($node, $action, $handler);
  359. }
  360. /**
  361. * Returns a registered node action handler.
  362. * @param $node the name of the node
  363. * @param $action the node action
  364. * @return handler functionname or object (is_subclass_of atkActionHandler) or
  365. * NULL if no handler exists for the specified action
  366. */
  367. function &atkGetNodeHandler($node, $action)
  368. {
  369. global $g_nodeHandlers;
  370. if (isset($g_nodeHandlers[$node][$action])) $handler = $g_nodeHandlers[$node][$action];
  371. elseif (isset($g_nodeHandlers["*"][$action])) $handler = $g_nodeHandlers["*"][$action];
  372. else $handler = NULL;
  373. return $handler;
  374. }
  375. /**
  376. * Registers a new node action handler.
  377. * @param String $node the name of the node (* matches all)
  378. * @param String $action the node action
  379. * @param String/atkActionHandler $handler handler functionname or object (is_subclass_of atkActionHandler)
  380. * @return bool true if there is no known handler
  381. */
  382. function atkRegisterNodeHandler($node, $action, $handler)
  383. {
  384. global $g_nodeHandlers;
  385. if (isset($g_nodeHandlers[$node][$action])) return FALSE;
  386. else $g_nodeHandlers[$node][$action] = $handler;
  387. return TRUE;
  388. }
  389. /**
  390. * Registers a new node action handler.
  391. *
  392. * @param string $node the name of the node (* matches all)
  393. * @param string $action the node action
  394. * @param string $class node handler class ATK path
  395. *
  396. * @return bool true if there is no known handler
  397. *
  398. * @deprecated
  399. * @see atkRegisterNodeHandler
  400. */
  401. function atkRegisterNodeHandlerClass($node, $action, $class)
  402. {
  403. atkRegisterNodeHandler($node, $action, $class);
  404. }
  405. /**
  406. * Returns a registered node controller.
  407. * @param String $node the name of the node
  408. * @return object (is_subclass_of atkController)
  409. * NULL if no controller exists for the specified node
  410. */
  411. function &atkGetNodeController($node)
  412. {
  413. global $g_nodeControllers;
  414. if (isset($g_nodeControllers[$node])) return $g_nodeControllers[$node];
  415. elseif (isset($g_nodeControllers["*"])) return $g_nodeControllers["*"];
  416. else return NULL;
  417. }
  418. /**
  419. * Registers a new node controller.
  420. * @param String $node the name of the node (* matches all)
  421. * @param atkController $controller object (is_subclass_of atkController)
  422. * @return bool true if there is no known handler
  423. */
  424. function atkRegisterNodeController($node, &$controller)
  425. {
  426. global $g_nodeControllers;
  427. if (isset($g_nodeControllers[$node])) return FALSE;
  428. else $g_nodeControllers[$node] = &$controller;
  429. return TRUE;
  430. }
  431. /**
  432. * Perform a member function on all active modules, and return the
  433. * collective result.
  434. *
  435. * <b>Example:</b>
  436. * <code>
  437. * $menuitems = atkHarvestModules("getStuff");
  438. * </code>
  439. * This will return the result of the getStuff calls for all modules in a
  440. * single array.
  441. *
  442. * @param String $function The name of the module member function to be
  443. * called. The function does not have to exist for
  444. * all modules, as atkHarvestModules will check if
  445. * it exists before it makes the call.
  446. * @param mixed $param Parameter to be passed to all functions. It is only
  447. * possible to pass zero or one parameter.
  448. * @param boolean $associative If true, return is an associative array with
  449. * the results indexed by modulename. If false,
  450. * results are put together in one array.
  451. * @return array The result of the harvest.
  452. */
  453. function atkHarvestModules($function, $param="", $associative=false)
  454. {
  455. $modules = atkGetModules();
  456. $modulekeys = array_keys($modules);
  457. $total = array();
  458. foreach ($modulekeys as $modname)
  459. {
  460. $module = &getModule($modname);
  461. if (is_object($module) && method_exists($module, $function))
  462. {
  463. $res = $module->$function($param);
  464. if (!empty($res))
  465. {
  466. if ($associative)
  467. {
  468. $total[$modname] = $res;
  469. }
  470. else
  471. {
  472. if (is_array($res))
  473. {
  474. $total = array_merge($total, $res);
  475. }
  476. else
  477. {
  478. $total[] = $res;
  479. }
  480. }
  481. }
  482. }
  483. }
  484. return $total;
  485. }
  486. /**
  487. * Get/set the status of the readoptimizer.
  488. * If you need the dataread-functionality of atkNode but don't need
  489. * the ui stuff, or the data write stuff, you can turn on the read
  490. * optimizer, so nodes load faster.
  491. * If you call this function without parameters (or NULL as param)
  492. * the optimizer value is not changed, and the function will just
  493. * return the current setting.
  494. * If you do specify a parameter, the function will return the
  495. * OLD setting (so you might reset it to the old value after you're
  496. * finished with the current node.
  497. *
  498. * @param $newvalue New value of the readoptimizer. true turns the
  499. * optimizer on. Falls turns it off.
  500. * @return boolean The old value of the optimizer setting, if a new
  501. * setting was passed OR
  502. * The current value if no new setting was passed.
  503. */
  504. function atkReadOptimizer($newvalue=NULL)
  505. {
  506. static $s_optimized=false;
  507. if (!($newvalue===NULL)) // New value was set
  508. {
  509. $oldvalue = $s_optimized;
  510. $s_optimized=$newvalue;
  511. return $oldvalue;
  512. }
  513. else
  514. {
  515. return $s_optimized; // Return current value.
  516. }
  517. }
  518. /**
  519. * Preload the module
  520. * @see atkPreloadModules()
  521. * @param String $modname The modulename
  522. * @param String $modpath The path to the module.
  523. */
  524. function atkPreloadModule($modname, $modpath)
  525. {
  526. global $g_modifiers, $g_overloaders, $g_nodeListeners;
  527. $preload = "$modpath/module_preload.inc";
  528. $module = "$modpath/module.inc";
  529. $filename = file_exists($preload) ? $preload : $module;
  530. // no module file exists
  531. if (!file_exists($filename))
  532. {
  533. atkdebug("Couldn't find module_preload.inc or module.inc for module '$modname' in '$modpath'");
  534. return;
  535. }
  536. if ($filename != $preload)
  537. {
  538. atkdebug("Loading module - $modname");
  539. atkimport("atk.modules.atkmodule");
  540. $corporate_base = atkconfig("corporate_module_base");
  541. if ($corporate_base!="")
  542. {
  543. atkimport($corporate_base);
  544. }
  545. }
  546. // the include file may specify modifiers.
  547. $modifiers = array();
  548. $overloaders = array();
  549. $listeners = array();
  550. include_once($filename);
  551. for ($i=0, $_i = count($modifiers); $i < $_i; $i++)
  552. $g_modifiers[$modifiers[$i]][] = $modname;
  553. if (count($overloaders) > 0)
  554. $g_overloaders = array_merge($g_overloaders, $overloaders);
  555. if (count($listeners) > 0)
  556. $g_nodeListeners = array_merge_recursive($g_nodeListeners, $listeners);
  557. }
  558. /**
  559. * Preloads all modules. If a module_preload.inc file exists in the
  560. * module directory, this file will be included. If no module_preload.inc
  561. * file exists in the module directory the module.inc file will be used
  562. * instead (to remain backwards compatible).
  563. */
  564. function atkPreloadModules()
  565. {
  566. global $g_moduleflags;
  567. $modules = atkGetModules();
  568. foreach ($modules as $modname => $modpath)
  569. {
  570. if ((!isset($g_moduleflags[$modname])) || (!hasFlag($g_moduleflags[$modname], MF_NO_PRELOAD)))
  571. {
  572. atkPreloadModule($modname, $modpath);
  573. }
  574. }
  575. }
  576. ?>