View source
<?php
function _crumbs_load_plugin_engine() {
$plugins = crumbs_get_plugins();
$weights = _crumbs_load_weights();
$disabled_keys = _crumbs_get_disabled_keys($plugins);
foreach ($disabled_keys as $key => $disabled) {
if (!isset($weights[$key])) {
$weights[$key] = FALSE;
}
}
return new crumbs_PluginEngine($plugins, $weights);
}
function crumbs_get_plugins() {
static $_plugins;
if (!isset($_plugins)) {
$_plugins = _crumbs_load_plugins();
}
return $_plugins;
}
function _crumbs_load_plugins() {
foreach (array(
'crumbs',
'menu',
'forum',
'views_ui',
'og',
'clickpath',
'taxonomy',
'path',
'pathauto',
'nodereference',
) as $module) {
if (module_exists($module)) {
module_load_include('inc', 'crumbs', 'plugins/crumbs.' . $module);
}
}
$plugins = array();
foreach (module_implements('crumbs_plugins') as $module) {
$function = $module . '_crumbs_plugins';
$module_plugins = $function();
if (is_array($module_plugins)) {
foreach ($module_plugins as $key => $plugin) {
$plugins[$module . '.' . $key] = $plugin;
}
}
else {
$plugins[$module] = $module_plugins;
}
}
return $plugins;
}
function _crumbs_load_weights() {
$weights = variable_get('crumbs_weights', NULL);
if (!is_array($weights)) {
$weights = _crumbs_load_weights_1_x();
}
$weights = is_array($weights) ? $weights : array();
asort($weights);
if (!isset($weights['*'])) {
$weights['*'] = count($weights);
}
return $weights;
}
function _crumbs_load_weights_1_x() {
$weights_1_x = variable_get('crumbs', array());
$weights_1_x = is_array($weights_1_x) ? $weights_1_x : array();
$weights = array();
$weight = 0;
foreach ($weights_1_x as $key_1_x => $enabled) {
$key = str_replace(':', '.', $key_1_x);
if ($enabled) {
$weights[$key] = $weight;
++$weight;
}
else {
$weights[$key] = FALSE;
}
}
return $weights;
}
function _crumbs_get_disabled_keys(array $plugins) {
$disabled_keys = array();
foreach ($plugins as $plugin_key => $plugin) {
if (method_exists($plugin, 'disabledByDefault')) {
foreach ($plugin
->disabledByDefault() as $suffix) {
if (!isset($suffix) || $suffix === '') {
$disabled_keys[$plugin_key] = TRUE;
}
else {
$disabled_keys[$plugin_key . '.' . $suffix] = TRUE;
}
}
}
}
return $disabled_keys;
}
function _crumbs_sort_plugins___DISABLED(array &$plugins, array $key_weights) {
$plugin_weights = array();
foreach ($plugins as $plugin_key => $plugin) {
$fragments = explode('.', $plugin_key);
$partial_key = array_shift($fragments);
$weight = 0;
if (isset($key_weights['*'])) {
$weight = $key_weights['*'];
}
while (TRUE) {
if (isset($key_weights[$partial_key . '.*'])) {
$weight = $key_weights[$partial_key . '.*'];
}
if (empty($fragments)) {
break;
}
$partial_key .= '.' . array_shift($fragments);
}
if (isset($key_weights[$plugin_key])) {
$weight = $key_weights[$plugin_key];
}
$plugin_weights[$plugin_key] = $weight;
}
foreach ($key_weights as $key => $weight) {
$fragments = explode('.', $key);
$partial_key = array_shift($fragments);
$plugin_key = NULL;
while (TRUE) {
if (isset($plugins[$partial_key])) {
$plugin_key = $partial_key;
}
if (empty($fragments)) {
break;
}
$partial_key .= '.' . array_shift($fragments);
}
if (isset($plugin_key)) {
if ($plugin_weights[$plugin_key] === FALSE || $plugin_weights[$plugin_key] > $weight) {
$plugin_weights[$plugin_key] = $weight;
}
}
}
array_multisort($plugin_weights, $plugins);
foreach ($plugins as $plugin_key => $plugin) {
if ($plugin_weights[$plugin_key] === FALSE) {
unset($plugins[$plugin_key]);
}
}
}
class crumbs_PluginEngine {
protected $_plugins;
protected $_weightKeeper;
protected $_pluginOrder_find = array();
protected $_pluginOrder_alter = array();
function __construct(array $plugins, array $weights) {
$this->_plugins = $plugins;
foreach ($plugins as $plugin_key => $plugin) {
if (!method_exists($plugin, 'defineOne')) {
$weights[$plugin_key] = FALSE;
}
if (!method_exists($plugin, 'defineMany') && !method_exists($plugin, 'define')) {
$weights[$plugin_key . '.*'] = FALSE;
}
}
$this->_weightKeeper = new crumbs_RuleWeightKeeper($weights);
foreach ($plugins as $plugin_key => $plugin) {
$keeper = $this->_weightKeeper
->prefixedWeightKeeper($plugin_key);
$w_find = $keeper
->getSmallestWeight();
if ($w_find !== FALSE) {
$this->_pluginOrder_find[$plugin_key] = $w_find;
}
$w_alter = $keeper
->findWeight();
if ($w_alter !== FALSE) {
$this->_pluginOrder_alter[$plugin_key] = $w_alter;
}
}
asort($this->_pluginOrder_find);
arsort($this->_pluginOrder_alter);
foreach ($this->_pluginOrder_find as $plugin_key => $weight) {
$this->_pluginOrder_find[$plugin_key] = $plugins[$plugin_key];
}
foreach ($this->_pluginOrder_alter as $plugin_key => $weight) {
$this->_pluginOrder_alter[$plugin_key] = $plugins[$plugin_key];
}
}
function invokeAll_find(crumbs_InvokeActionInterface_find $invoke_action) {
foreach ($this->_pluginOrder_find as $plugin_key => $plugin) {
$weight_keeper = $this->_weightKeeper
->prefixedWeightKeeper($plugin_key);
$found = $invoke_action
->invoke($plugin, $plugin_key, $weight_keeper);
if ($found) {
return $found;
}
}
}
function invokeAll_alter(crumbs_InvokeActionInterface_alter $invokeAction) {
foreach ($this->_pluginOrder_alter as $plugin_key => $plugin) {
$invokeAction
->invoke($plugin, $plugin_key);
}
}
}
class crumbs_RuleWeightKeeper {
protected $_rule_weights;
protected $_prefixedKeepers = array();
protected $_prefixSorted = array();
protected $_soloSorted = array();
function __construct(array $rule_weights) {
asort($rule_weights);
$this->_rule_weights = $rule_weights;
}
function prefixedWeightKeeper($prefix) {
if (!isset($this->_prefixedKeepers[$prefix])) {
$this->_prefixedKeepers[$prefix] = $this
->_buildPrefixedWeightKeeper($prefix);
}
return $this->_prefixedKeepers[$prefix];
}
protected function _buildPrefixedWeightKeeper($prefix) {
$weights = array();
$k = strlen($prefix);
$weights[''] = $weights['*'] = $this
->_findWildcardWeight($prefix);
if (isset($this->_rule_weights[$prefix])) {
$weights[''] = $this->_rule_weights[$prefix];
}
if (isset($this->_rule_weights[$prefix . '.*'])) {
$weights['*'] = $this->_rule_weights[$prefix . '.*'];
}
foreach ($this->_rule_weights as $key => $weight) {
if (strlen($key) > $k && substr($key, 0, $k + 1) === $prefix . '.') {
$weights[substr($key, $k + 1)] = $weight;
}
}
return new crumbs_RuleWeightKeeper($weights);
}
function getSmallestWeight() {
foreach ($this->_rule_weights as $weight) {
if ($weight !== FALSE) {
return $weight;
}
}
return FALSE;
}
function findWeight($key = NULL) {
if (!isset($key)) {
return $this->_rule_weights[''];
}
if (isset($this->_rule_weights[$key])) {
return $this->_rule_weights[$key];
}
return $this
->_findWildcardWeight($key);
}
protected function _findWildcardWeight($key) {
$fragments = explode('.', $key);
$partial_key = array_shift($fragments);
$weight = $this->_rule_weights['*'];
while (!empty($fragments)) {
if (isset($this->_rule_weights[$partial_key . '.*'])) {
$weight = $this->_rule_weights[$partial_key . '.*'];
}
$partial_key .= '.' . array_shift($fragments);
}
return $weight;
}
}
abstract class crumbs_InvokeAction_findForPath implements crumbs_InvokeActionInterface_find {
protected $_path;
protected $_item;
protected $_method;
protected $_methods = array();
protected $_candidate_key;
protected $_candidate_value;
protected $_candidate_weight;
protected $_log;
function __construct($path, $item) {
$this->_path = $path;
$this->_item = $item;
$method_suffix = crumbs_build_method_suffix($item['path']);
if ($method_suffix !== FALSE) {
$this->_methods[] = $this->_method . '__' . $method_suffix;
}
$this->_methods[] = $this->_method;
}
function invoke($plugin, $plugin_key, $weight_keeper) {
$smallest_weight = $weight_keeper
->getSmallestWeight();
if (isset($this->_candidate_weight) && $this->_candidate_weight <= $smallest_weight) {
return TRUE;
}
foreach ($this->_methods as $method) {
if (method_exists($plugin, $method)) {
$result = $this
->_invoke($plugin, $method);
break;
}
}
if (method_exists($plugin, 'defineMany') || method_exists($plugin, 'define')) {
if (is_array($result) && !empty($result)) {
foreach ($result as $key => $value) {
$weight = $weight_keeper
->findWeight($key);
$this
->_setValue($plugin_key . '.' . $key, $value, $weight);
}
}
else {
$this->_log[$plugin_key . '.*'] = array(
NULL,
NULL,
);
}
}
else {
if (isset($result)) {
$weight = $weight_keeper
->findWeight();
$this
->_setValue($plugin_key, $result, $weight);
}
else {
$this->_log[$plugin_key] = array(
NULL,
NULL,
);
}
}
}
function getValue() {
return $this->_candidate_value;
}
function getCandidateKey() {
return $this->_candidate_key;
}
function getLoggedCandidates() {
return $this->_log;
}
protected function _setValue($key, $value, $weight) {
if ($weight !== FALSE) {
if (!isset($this->_candidate_weight) || $weight < $this->_candidate_weight) {
$this->_candidate_weight = $weight;
$this->_candidate_value = $value;
$this->_candidate_key = $key;
}
}
$this->_log[$key] = array(
$value,
$weight,
);
}
protected function _getMethods($method) {
return array(
$method,
$method . '__' . $this->_method_suffix,
);
}
protected abstract function _invoke($plugin, $method);
}