'admin/pathmenu', // 'title' =>t('path menus'), // 'callback'=>'pathmenu_admin', // 'access' =>user_access('administer pathmenu'), 'path' => 'admin/settings/pathmenu', 'title' => t('Path menus'), 'description' => t('Define breadcrumb and menus from paths.'), 'callback' => 'drupal_get_form', 'callback arguments' => 'pathmenu_admin', 'access' => user_access('administer pathmenu'), 'type' => MENU_NORMAL_ITEM, ); } else { // Retrieve the compiled code of rules (PHP code) $phpcode=variable_get('pathmenu_phpcode','return TRUE;'); // Execute the rules and merge the result with the items returned by the hook $items=array_merge($items,_pathmenu_execute_rules($phpcode)); } return $items; } /** * Menu callback; generate the form to edit the rules. */ function pathmenu_admin() { // Initializes the form structure $form=array(); // Adds a textarea which will hold the rules source code $form['rules']=array( '#type' => 'textarea', '#title' => t('Rules'), '#default_value'=> variable_get('pathmenu_rules', ''), '#rows' => 20, '#description' => t('List of rules.'), ); // Adds the submit button $form['submit']=array( '#type' =>'submit', '#value'=>t('Save') ); // Adds a list of every available condition with help $conditions_help=module_invoke_all('pmcondition','getlist'); $help=''; foreach($conditions_help as $condition_name=>$condition_help) { $help.='
".var_export($phpcode,TRUE).""); global $user; // Determine the URI, omitting the /?q= if mod_rewrite is not enabled // $url=$_SERVER['REQUEST_URI']; // if(substr($url,0,4)=='/?q=') { // $url=substr($url,4); // } $url = drupal_get_path_alias($_GET["q"]); //print("
".var_export($url,TRUE).""); // Determine if the current shows a node or something else if(arg(0)=='node' and is_numeric($nodenid=arg(1)) and is_null(arg(2))) { // The current page shows a node, loads information about it $node =node_load($nodenid); $nodetype =$node->type; if(module_exists("taxonomy")) { $nodeterms =array_keys(taxonomy_node_get_terms($nodenid)); } else { $nodeterms =array(); } } else { // The current page does not show a node, defines default values $nodenid =''; $nodetype =''; $nodeterms =array(); } // Execute the compiled code eval($phpcode); //if($nodetype=='biography') { // menu_set_location( // array( // menu_get_item(NULL,'about/team'), // array( // 'path'=>'$url', // 'title'=>'Nothing', // 'type'=>MENU_VISIBLE_IN_BREADCRUMB // ) // ) // ); // //return TRUE; //} ////return TRUE; // Returns the array containing the menu items added by the different rules return pathmenu_add_menu(); } /** * Keep memory of menu items added by the different rules. This * function must be called by any action that adds a menu item. * * @param $item * item menu to add, must be an array (see hook_menu for more info), * if $item is not specified, the function returns an array of all * the previously added menu items * @return * an array containing the menu items added by the different * rules (see hook_menu for more info) */ function pathmenu_add_menu($item=NULL) { static $items; // Initialize $items if it has not be if(!is_array($items)) $items=array(); // If a menu item is specified, add it to the list if($item) { // Add the menu item to the list $items[]=$item; } else { // Returns the list of menu items return $items; } } /** * Compile rules : generate PHP code from a list of rules. * * @param $rules * a structured array containing the rules to compile with the following * structure * array( * 0=>array( * 'conditions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ), * 'actions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ) * ), * 1=>array( * ... * ) * ) * @return * a string containing the PHP code that will be executed by eval or * FALSE if there was one error */ function _pathmenu_compile_rules($rules) { $rules_code=''; // $rules must be an array if(!is_array($rules)) return FALSE; if(count($rules)==0) return 'return TRUE;'; // Retrieves available conditions and actions among every module that // supports them through hook_pmcondition and hook_pmaction $available_conditions=array_keys(module_invoke_all('pmcondition','getlist')); $available_actions =array_keys(module_invoke_all('pmaction' ,'getlist')); // Scans each rule foreach($rules as $rule) { // Initializes the conditions for this rule $conditions_codes=array(); // For the current rule, scans each condition foreach($rule['conditions'] as $condition) { // Checks if the condition has been defined if(in_array($condition['function'],$available_conditions)) { // The condition has been defined, retrieve the PHP code (=compile) $conditions_codes[]=implode('',module_invoke_all( 'pmcondition', 'getcode', $condition['function'], $condition['parameter'] )); } else { // The condition has not been defined ==> error ! drupal_set_message( t( "Unknown condition [%condition].", array( "%condition"=>$condition['function']) ), 'error' ); return FALSE; } } // Every condition will be ANDed $conditions_code="if(".implode(" and ",$conditions_codes).")"; // Initializes the actions for this rule $actions_codes=array(); // For the current rule, scans each action foreach($rule['actions'] as $action) { // Checks if the action has been defined if(in_array($action['function'],$available_actions)) { // The action has been defined, retrieve the PHP code (=compile) $actions_codes[]=implode('',module_invoke_all( 'pmaction', 'getcode', $action['function'], $action['parameter'] )); } else { // The action has not been defined ==> error ! drupal_set_message( t( "Unknown action [%action].", array( "%action"=>$action['function']) ), 'error' ); return FALSE; } } // Every action will be executed one after the other, then exit // as an executed rule ends everything $actions_code=implode('',$actions_codes)."return TRUE;"; // Add the compiled code for the current rule to the global code $rules_code.=$conditions_code.'{'.$actions_code.'}'; } // Returns the compiled code return $rules_code."return TRUE;"; } /** * Analyze rules source code for correct syntax * * @param $rules * a string containing rules source code, one rule per line, * comments line starting with //, empty lines are ignored * @return * a structured array containing the rules to compile with the following * structure, or FALSE if there was an error * array( * 0=>array( * 'conditions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ), * 'actions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ) * ), * 1=>array( * ... * ) * ) */ function _pathmenu_analyze_rules($rules) { // Initializes variables $comment =array(); $row =strtok($rules,"\r\n"); $analyze =array(); $linenumber=1; while($row!==FALSE) { // Ignore empty rows if(trim($row)) { // Row can be either comment or rule if(substr($row,0,2)=='//') { // Keep memory of comment rows $comment[]=$row; } else { // Analyze a new rule $rule=_pathmenu_analyze_rule($row); if(!$rule) { // Rule is not well written ==> error ! drupal_set_message( t( "Rule is not well written on line %line", array( '%line'=>$linenumber ) ), 'error' ); return FALSE; } // Add the comments to the rule $rule['comment']=implode("\n",$comment); $comment=array(); $analyze[]=$rule; } } // Get next row $row=strtok("\r\n"); $linenumber++; } return $analyze; } function _pathmenu_analyze_element($element) { $pattern='/^([^()]+)\(([^()]+)\)$/'; $matches=array(); $nb=preg_match($pattern,trim($element),$matches); if($nb==0) return FALSE; return array( 'function' =>trim($matches[1]), 'parameter'=>trim($matches[2]) ); } /** * Analyze one rule source code for correct syntax * * @param $rule * a string containing 1 rule source code with no comment * @return * a structured array containing the rule to compile with the following * structure, or FALSE if there was an error * array( * 'conditions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ), * 'actions'=>array( * 0=>array( * 'function'=>string * 'parameter'=>string * ), * 1=>array( * ... * ) * ) * ) */ function _pathmenu_analyze_rule($rule) { $elements=array( 'conditions'=>array(), 'actions' =>array() ); // a rule is composed of a condition and an action separated by '->' if(($separator_position=strpos($rule,'->'))===FALSE) return FALSE; $condition=trim(substr($rule,0,$separator_position)); $action =trim(substr($rule,$separator_position+2)); // Checks if there a condition and an action if(!$condition or !$action) return FALSE; // a condition may be composed of subconditions separated by '+' $subconditions=explode('+',$condition); foreach($subconditions as $subcondition) { // Analyzes one condition $funcparm=_pathmenu_analyze_element($subcondition); if(!$funcparm) return FALSE; $elements['conditions'][]=$funcparm; } // an action may be composed of subactions separated by '+' $subactions=explode('+',$action); foreach($subactions as $subaction) { // Analyzes one action $funcparm=_pathmenu_analyze_element($subaction); if(!$funcparm) return FALSE; $elements['actions'][]=$funcparm; } return $elements; }