PageRenderTime 54ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/profiles/opigno_lms/modules/contrib/crumbs/lib/PluginSystem/PluginInfo.php

https://bitbucket.org/gunnarslette/mme-opigno-demo
PHP | 482 lines | 249 code | 40 blank | 193 comment | 21 complexity | 04b56e17721d2f5dfdd1522226fab67c MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-2.0, CC-BY-SA-3.0, BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Info about available plugins and their weights.
  4. *
  5. * @property array $weights
  6. * @property crumbs_Container_WeightMap $weightMap
  7. * @property array $defaultWeights
  8. *
  9. * @property true[][] $routelessPluginMethodsUnsorted
  10. * Format: $['findParent'][$plugin_key] = true
  11. * @property true[][][] $routePluginMethodsUnsorted
  12. * Format: $['findParent'][$route][$plugin_key] = true.
  13. *
  14. * @property true[][] $pluginRoutelessMethods
  15. * Format: $[$pluginKey]['findParent'] = true
  16. * @property true[][][] $pluginRouteMethods
  17. * Format: $[$pluginKey]['findParent'][$route] = true
  18. *
  19. * @property true[][] $routelessPluginMethods
  20. * Format: $['findParent'][$plugin_key] = true
  21. * @property true[][][] $routePluginMethods
  22. * Format: $['findParent'][$route][$plugin_key] = true.
  23. *
  24. * @property array $userWeights
  25. * @property crumbs_Container_MultiWildcardData $availableKeysMeta
  26. * @property crumbs_Container_MultiWildcardDataOffset[][] $availableKeysMetaGrouped
  27. * Format: $['inherit'][$key] = $meta
  28. *
  29. * @property crumbs_PluginInterface[] $plugins
  30. * @property array $pluginsCached
  31. *
  32. * @property crumbs_InjectedAPI_Collection_CollectionResult $discovery
  33. * The result of running hook_crumbs_plugins()
  34. *
  35. * @property array $pluginOrder
  36. * @property array $pluginsSorted
  37. * @property bool $includePluginFiles
  38. */
  39. class crumbs_PluginSystem_PluginInfo extends crumbs_Container_AbstractLazyDataCached {
  40. /**
  41. * Which keys to load from persistent cache.
  42. *
  43. * @return string[]
  44. */
  45. protected function keysToCache() {
  46. // Plugin cache is special, because these are objects.
  47. // If this fails, we want to totally circumvent the cache.
  48. $callback_before = ini_get('unserialize_callback_func');
  49. ini_set('unserialize_callback_func', '_crumbs_unserialize_failure');
  50. try {
  51. // Trigger $this->__get('plugins').
  52. $this->plugins;
  53. }
  54. catch (crumbs_UnserializeException $exception) {
  55. // Don't cache anything this round.
  56. return array();
  57. }
  58. ini_set('unserialize_callback_func', $callback_before);
  59. return array('weights', 'pluginsCached', 'defaultWeights', 'pluginRoutes', 'pluginOrder');
  60. }
  61. /**
  62. * Combination of user-defined weights and default weights
  63. *
  64. * @return array
  65. *
  66. * @see crumbs_PluginSystem_PluginInfo::$weights
  67. */
  68. protected function get_weights() {
  69. $weights = $this->defaultWeights;
  70. foreach ($this->userWeights as $key => $weight) {
  71. // Make sure to skip NULL values.
  72. if (isset($weight)) {
  73. $weights[$key] = $weight;
  74. }
  75. }
  76. return $weights;
  77. }
  78. /**
  79. * Object that can calculate rule weights based on the weight settings.
  80. * (which are often wildcards)
  81. *
  82. * @return crumbs_Container_WeightMap
  83. *
  84. * @see crumbs_PluginSystem_PluginInfo::$weightMap
  85. */
  86. protected function get_weightMap() {
  87. return new crumbs_Container_WeightMap($this->weights);
  88. }
  89. /**
  90. * Default weights without the user configuration
  91. *
  92. * @return array
  93. *
  94. * @see crumbs_PluginSystem_PluginInfo::$defaultWeights
  95. */
  96. protected function get_defaultWeights() {
  97. return $this->discovery->getDefaultValues();
  98. }
  99. /**
  100. * @return true[][][]
  101. * Format: $['findParent'][$route][$plugin_key] = true.
  102. *
  103. * @see crumbs_PluginSystem_PluginInfo::$routePluginMethodsUnsorted
  104. */
  105. protected function get_routePluginMethodsUnsorted() {
  106. return $this->discovery->getRoutePluginMethods();
  107. }
  108. /**
  109. * @return true[][]
  110. * Format: $['findParent'][$plugin_key] = true
  111. *
  112. * @see crumbs_PluginSystem_PluginInfo::$routelessPluginMethodsUnsorted
  113. */
  114. protected function get_routelessPluginMethodsUnsorted() {
  115. return $this->discovery->getRoutelessPluginMethods();
  116. }
  117. /**
  118. * @return true[][]
  119. * Format: $[$pluginKey]['findParent'] = true
  120. *
  121. * @see crumbs_PluginSystem_PluginInfo::$pluginRoutelessMethods
  122. */
  123. protected function get_pluginRoutelessMethods() {
  124. return $this->discovery->getPluginRoutelessMethods();
  125. }
  126. /**
  127. * @return true[][][]
  128. * Format: $[$pluginKey]['findParent'] = true
  129. *
  130. * @see crumbs_PluginSystem_PluginInfo::$pluginRouteMethods
  131. */
  132. protected function get_pluginRouteMethods() {
  133. return $this->discovery->getPluginRouteMethods();
  134. }
  135. /**
  136. * @return true[][][]
  137. * Format: $['findParent'][$route][$plugin_key] = true.
  138. *
  139. * @see crumbs_PluginSystem_PluginInfo::$routePluginMethods
  140. */
  141. protected function get_routePluginMethods() {
  142. $unsorted_all = $this->routePluginMethodsUnsorted;
  143. $types = array(
  144. 'decorateBreadcrumb' => 'alter',
  145. 'findParent' => 'find',
  146. 'findTitle' => 'find',
  147. );
  148. $order = $this->pluginOrder;
  149. $sorted_all = array();
  150. foreach ($types as $base_method_name => $type) {
  151. if (!isset($unsorted_all[$base_method_name])) {
  152. continue;
  153. }
  154. foreach ($unsorted_all[$base_method_name] as $route => $unsorted) {
  155. $sorted = $this->sortPluginMethods($unsorted_all[$base_method_name][$route], $order[$type]);
  156. if (!empty($sorted)) {
  157. $sorted_all[$base_method_name][$route] = $sorted;
  158. }
  159. }
  160. }
  161. return $sorted_all;
  162. }
  163. /**
  164. * @return true[][]
  165. * Format: $['findParent'][$plugin_key] = $method
  166. *
  167. * @see crumbs_PluginSystem_PluginInfo::$routelessPluginMethods
  168. */
  169. protected function get_routelessPluginMethods() {
  170. $unsorted = $this->routelessPluginMethodsUnsorted;
  171. $types = array(
  172. 'decorateBreadcrumb' => 'alter',
  173. 'findParent' => 'find',
  174. 'findTitle' => 'find',
  175. );
  176. $order = $this->pluginOrder;
  177. $sorted_all = array();
  178. foreach ($types as $base_method_name => $type) {
  179. if (!isset($unsorted[$base_method_name])) {
  180. continue;
  181. }
  182. $sorted = $this->sortPluginMethods($unsorted[$base_method_name], $order[$type]);
  183. if (!empty($sorted)) {
  184. $sorted_all[$base_method_name] = $sorted;
  185. }
  186. }
  187. return $sorted_all;
  188. }
  189. /**
  190. * @param string[] $plugin_methods
  191. * @param mixed[] $order
  192. *
  193. * @return array
  194. */
  195. private function sortPluginMethods(array $plugin_methods, array $order) {
  196. $sorted = array();
  197. foreach ($order as $plugin_key => $x) {
  198. if (isset($plugin_methods[$plugin_key])) {
  199. $sorted[$plugin_key] = $plugin_methods[$plugin_key];
  200. }
  201. }
  202. return $sorted;
  203. }
  204. /**
  205. * User-defined weights
  206. *
  207. * @return array
  208. *
  209. * @see crumbs_PluginSystem_PluginInfo::$userWeights
  210. */
  211. protected function get_userWeights() {
  212. $user_weights = variable_get('crumbs_weights', array(
  213. // The user expects the crumbs.home_title plugin to be dominant.
  214. // @todo There must be a better way to do this.
  215. 'crumbs.home_title' => 0,
  216. ));
  217. // '*' always needs to be set.
  218. if (!isset($user_weights['*'])) {
  219. // Put '*' last.
  220. $max = -1;
  221. foreach ($user_weights as $k => $v) {
  222. if ($v >= $max) {
  223. $max = $v;
  224. }
  225. }
  226. $user_weights['*'] = $max + 1;
  227. }
  228. return $user_weights;
  229. }
  230. /**
  231. * @return crumbs_Container_MultiWildcardData
  232. *
  233. * @see crumbs_PluginSystem_PluginInfo::$availableKeysMeta
  234. */
  235. protected function get_availableKeysMeta() {
  236. $op = new crumbs_PluginOperation_describe();
  237. /**
  238. * @var crumbs_PluginInterface $plugin
  239. */
  240. foreach ($this->plugins as $plugin_key => $plugin) {
  241. $op->invoke($plugin, $plugin_key);
  242. }
  243. foreach ($this->defaultWeights as $key => $default_weight) {
  244. $op->setDefaultWeight($key, $default_weight);
  245. }
  246. $info = $op->collectedInfo();
  247. $info->basicMethods = $this->pluginRoutelessMethods;
  248. $info->routeMethods = $this->pluginRouteMethods;
  249. return $info;
  250. }
  251. /**
  252. * @return crumbs_Container_MultiWildcardDataOffset[][]
  253. * Format: $['inherit'][$key] = $meta
  254. *
  255. * @see crumbs_PluginSystem_PluginInfo::$availableKeysMetaGrouped
  256. */
  257. protected function get_availableKeysMetaGrouped() {
  258. $sectionKeys = array();
  259. foreach ($this->availableKeysMeta as $key => $meta) {
  260. $sectionKeys[$key] = 'inherit';
  261. }
  262. foreach ($this->defaultWeights as $key => $weight) {
  263. if (!isset($sectionKeys[$key])) {
  264. continue;
  265. }
  266. elseif (FALSE === $weight) {
  267. $sectionKeys[$key] = 'default:disabled';
  268. }
  269. else {
  270. $sectionKeys[$key] = "default:$weight";
  271. }
  272. }
  273. $weights = $this->weights;
  274. asort($weights);
  275. $enabled = array();
  276. foreach ($weights as $key => $weight) {
  277. if (!isset($sectionKeys[$key])) {
  278. continue;
  279. }
  280. elseif (FALSE === $weight) {
  281. $sectionKeys[$key] = 'disabled';
  282. }
  283. elseif (isset($sectionKeys[$key])) {
  284. $sectionKeys[$key] = 'enabled';
  285. $enabled[$key] = TRUE;
  286. }
  287. }
  288. $grouped = array(
  289. 'enabled' => $enabled,
  290. 'disabled' => array(),
  291. 'default:disabled' => array(),
  292. 'inherit' => array(),
  293. );
  294. foreach ($this->availableKeysMeta as $key => $meta) {
  295. $sectionKey = $sectionKeys[$key];
  296. $grouped[$sectionKey][$key] = $meta;
  297. }
  298. }
  299. /**
  300. * Plugins, not sorted, but already with the weights information.
  301. *
  302. * @return array
  303. *
  304. * @see crumbs_PluginSystem_PluginInfo::$plugins
  305. */
  306. protected function get_plugins() {
  307. // We use a trick to always include the plugin files, even if the plugins
  308. // are coming from the cache.
  309. $this->includePluginFiles;
  310. return $this->pluginsCached;
  311. }
  312. /**
  313. * Plugins, not sorted, but already with the weights information.
  314. *
  315. * @return array
  316. *
  317. * @see crumbs_PluginSystem_PluginInfo::$pluginsCached
  318. */
  319. protected function get_pluginsCached() {
  320. $plugins = $this->discovery->getPlugins();
  321. foreach ($plugins as $plugin_key => $plugin) {
  322. // Let plugins know about the weights, if they want to.
  323. if (method_exists($plugin, 'initWeights')) {
  324. $plugin->initWeights($this->weightMap->localWeightMap($plugin_key));
  325. }
  326. }
  327. return $plugins;
  328. }
  329. /**
  330. * Information returned from hook_crumbs_plugins()
  331. *
  332. * @return crumbs_InjectedAPI_Collection_CollectionResult
  333. *
  334. * @see crumbs_PluginSystem_PluginInfo::$discovery
  335. */
  336. protected function get_discovery() {
  337. $this->includePluginFiles;
  338. // Pass a by-reference parameter to the $api object, that can only be
  339. // changed from here.
  340. $api = new crumbs_InjectedAPI_hookCrumbsPlugins(
  341. $pluginCollection = new crumbs_InjectedAPI_Collection_PluginCollection,
  342. $entityPluginCollection = new crumbs_InjectedAPI_Collection_EntityPluginCollection,
  343. new crumbs_InjectedAPI_Collection_CallbackCollection,
  344. $defaultValueCollection = new crumbs_InjectedAPI_Collection_DefaultValueCollection);
  345. foreach (module_implements('crumbs_plugins') as $module) {
  346. $function = $module .'_crumbs_plugins';
  347. $api->setModule($module);
  348. $function($api);
  349. }
  350. $entityPluginCollection->finalize($pluginCollection);
  351. return new crumbs_InjectedAPI_Collection_CollectionResult($pluginCollection, $defaultValueCollection);
  352. }
  353. /**
  354. * Order of plugins, for 'find' and 'alter' operations.
  355. *
  356. * @return array
  357. * Format: $['find'][$pluginKey] = $weight.
  358. *
  359. * @see crumbs_PluginSystem_PluginInfo::$pluginOrder
  360. */
  361. protected function get_pluginOrder() {
  362. $order = array(
  363. 'find' => array(),
  364. 'alter' => array(),
  365. );
  366. // Sort the plugins, using the weights from weight map.
  367. $weightMap = $this->weightMap;
  368. foreach ($this->plugins as $plugin_key => $plugin) {
  369. if ($plugin instanceof crumbs_MultiPlugin) {
  370. $localWeightMap = $weightMap->localWeightMap($plugin_key);
  371. $w_find = $localWeightMap->smallestValue();
  372. if ($w_find !== FALSE) {
  373. $order['find'][$plugin_key] = $w_find;
  374. }
  375. // Multi plugins cannot participate in alter operations.
  376. }
  377. else {
  378. $weight = $weightMap->valueAtKey($plugin_key);
  379. if ($weight !== FALSE) {
  380. $order['find'][$plugin_key] = $weight;
  381. $order['alter'][$plugin_key] = $weight;
  382. }
  383. }
  384. }
  385. // Lowest weight first = highest priority first
  386. asort($order['find']);
  387. // Lowest weight last = highest priority last
  388. arsort($order['alter']);
  389. return $order;
  390. }
  391. /**
  392. * Sorted plugins for 'find' and 'alter' operations.
  393. *
  394. * @return array
  395. *
  396. * @see crumbs_PluginSystem_PluginInfo::$pluginsSorted
  397. */
  398. protected function get_pluginsSorted() {
  399. $sorted = $this->pluginOrder;
  400. $plugins = $this->plugins;
  401. foreach (array('find', 'alter') as $type) {
  402. foreach ($sorted[$type] as $plugin_key => &$x) {
  403. $x = $plugins[$plugin_key];
  404. }
  405. }
  406. return $sorted;
  407. }
  408. /**
  409. * Include files in the /plugin/ folder.
  410. * We use the cache mechanic to make sure this happens exactly once.
  411. *
  412. * @return bool
  413. *
  414. * @see crumbs_PluginSystem_PluginInfo::$includePluginFiles
  415. */
  416. protected function get_includePluginFiles() {
  417. $dir = drupal_get_path('module', 'crumbs') . '/plugins';
  418. $files = array();
  419. foreach (scandir($dir) as $candidate) {
  420. if (preg_match('/^crumbs\.(.+)\.inc$/', $candidate, $m)) {
  421. if (module_exists($m[1])) {
  422. $files[$m[1]] = $dir . '/' . $candidate;
  423. }
  424. }
  425. }
  426. // Organic groups is a special case,
  427. // because 7.x-2.x behaves different from 7.x-1.x.
  428. if (1
  429. && isset($files['og'])
  430. && !function_exists('og_get_group')
  431. ) {
  432. // We are using the og-7.x-1.x branch.
  433. $files['og'] = $dir . '/crumbs.og.2.inc';
  434. }
  435. // Since the directory order may be anything, sort alphabetically.
  436. ksort($files);
  437. foreach ($files as $file) {
  438. require_once $file;
  439. }
  440. return TRUE;
  441. }
  442. }