Created
September 14, 2011 14:02
-
-
Save larscwallin/1216634 to your computer and use it in GitHub Desktop.
simplx.controller, now with url routing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SIMPLX Controller V0.7 | |
UPDATE 111109 | |
NEW FEATURES: | |
- Added a whole bunch of modResource fields to the Request object. This means that you can route on stuff like: | |
pagetitle | |
template | |
parent | |
template | |
createdby | |
createdon | |
editedby | |
editedon | |
class_key | |
uri | |
content_type | |
published | |
pub_date | |
unpub_date | |
alias | |
isfolder | |
type | |
templatename | |
UPDATE 111028 | |
NEW FEATURES: | |
- The Plugin now supports Property Sets | |
This is very cool as it makes it possible to run different configurations, e.g. Routing Tables, at | |
different System Events. The Plugin Property Set has the exact same signature as the Snippet set. | |
UPDATE 111017 | |
NEW FEATURES: | |
- Routing Instructions now take default parameters. Very handy! | |
Example: "GET":["modapi.modchunk.get",{"myproperty":"My default value"}] | |
The previous, simple Instruction assignment of course still works | |
"GET":"modapi.modchunk.default" | |
UPDATE 111015 | |
NEW FEATURES: | |
- Now supports regular expressions :D By default, the separator which tells the controller to use regex is "?". See the REST table below for an example. | |
- You no longer have to specify a default routing constraint. If none is found the controller defaults to using the first constraint item in the routing table. | |
- Loads of fixes :) | |
* IMPORTANT: You need to get the new SimplxRequest Gist also (https://gist.github.com/1216951). | |
UPDATE 111005 | |
NEW FEATURES: | |
- Better structure to the Routing Table definition by adding named object collections ("constraints","rules","conditions") instead of implicit type naming. | |
This means that you can basically encode the json and get this interface: | |
$context = $routingtable->constraints->web; | |
$header = $context->header; | |
if($header->rules->content-type){ | |
print 'Hey, I can route on Content-Type!'; | |
} | |
I will however shortly make a proper OO PHP Class to manage the Routing Tables. | |
FIXES: | |
- Default routing was broken. I have done a whole bunch of unit testing cases and it seems to be working now. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
</head> | |
<body> | |
<h1>SIMPLX Controller 0.7</h1> | |
<h3>About</h3> | |
<p> | |
</p> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"contexts":{ | |
"web":{ | |
"constraints":{ | |
"header":{ | |
"rules":{ | |
"header:content-type":{ | |
"conditions":{ | |
"text/xml":"modapi.modchunk.default" | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"contexts":{ | |
"web":{ | |
"constraints":{ | |
"query.id=1":{ | |
"rules":{ | |
"method":{ | |
"conditions":{ | |
"GET":"modapi.modchunk.get", | |
"*":"modapi.modchunk.default" | |
} | |
}, | |
"*":"modapi.modchunk.default" | |
}, | |
"*":"modapi.modchunk.default" | |
}, | |
"*":"modapi.modchunk.default" | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"contexts":{ | |
"web":{ | |
"constraints":{ | |
"query":{ | |
"rules":{ | |
"query.id":{ | |
"conditions":{ | |
"1":"modapi.modchunk.get", | |
"2":"modapi.modchunk.update" | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"contexts":{ | |
"web":{ | |
"constraints":{ | |
"path?/modChunk/i":{ | |
"rules":{ | |
"method":{ | |
"conditions":{ | |
"GET":"modapi.modchunk.get", | |
"*":["modapi.modchunk.default",{"activity":"defaultCondition"}] | |
} | |
}, | |
"*":["modapi.modchunk.default",{"activity":"defaultRule"}] | |
} | |
}, | |
"*":["modapi.constraint.default",{"activity":"defaultConstraint"}] | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
MODx Snippet simplx.controller | |
Version 111108 | |
*/ | |
require_once($modx->getOption('core_path').'components/simplx/request/simplx.request.php'); | |
$activeProcesses = array(); | |
$parseError = false; | |
$routingTableObject = isset($routingTableObject) ? $routingTableObject : false; | |
$requestObject = isset($requestObject) ? $requestObject : SimplxRequest::getRequest(); | |
$fielddelimiter = isset($fielddelimiter) ? $fielddelimiter : '.'; | |
$valuedelimiter = isset($valuedelimiter) ? $valuedelimiter : '='; | |
$patterndelimiter = isset($patterndelimiter) ? $patterndelimiter : '?'; | |
$routingConstraintField = ''; | |
$constraintRoutingRules = ''; | |
$defaultruletoken = isset($defaultruletoken) ? $defaultruletoken : '*'; | |
$defaultconstrainttoken = isset($defaultconstrainttoken) ? $defaultconstrainttoken : '*'; | |
$currentResource = $modx->resource; | |
$currentResourceArray = array(); | |
SimplxRequest::$fieldDelimiter = $fielddelimiter; | |
SimplxRequest::$valueDelimiter = $valuedelimiter; | |
if($currentResource instanceof modResource){ | |
SimplxRequest::addSection('modresource'); | |
$currentResourceArray['pagetitle'] = $currentResource->get('pagetitle'); | |
$currentResourceArray['template'] = $currentResource->get('template'); | |
$currentResourceArray['parent'] = $currentResource->get('parent'); | |
$currentResourceArray['template'] = $currentResource->get('template'); | |
$currentResourceArray['createdby'] = $currentResource->get('createdby'); | |
$currentResourceArray['createdon'] = $currentResource->get('createdon'); | |
$currentResourceArray['editedby'] = $currentResource->get('editedby'); | |
$currentResourceArray['editedon'] = $currentResource->get('editedon'); | |
$currentResourceArray['class_key'] = $currentResource->get('class_key'); | |
$currentResourceArray['uri'] = $currentResource->get('uri'); | |
$currentResourceArray['content_type'] = $currentResource->get('content_type'); | |
$currentResourceArray['published'] = $currentResource->get('published'); | |
$currentResourceArray['pub_date'] = $currentResource->get('pub_date'); | |
$currentResourceArray['unpub_date'] = $currentResource->get('unpub_date'); | |
$currentResourceArray['alias'] = $currentResource->get('alias'); | |
$currentResourceArray['isfolder'] = $currentResource->get('isfolder'); | |
$currentResourceArray['type'] = $currentResource->get('type'); | |
$currentResourceArray['templatename'] = $currentResource->getOne('Template')->get('templatename'); | |
SimplxRequest::setSection('modresource',$currentResourceArray); | |
} | |
/* | |
Before anything else, we need to make sure that we have a routingtable set. If not, theres | |
no need to continue. | |
*/ | |
if(!$routingtable){ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: No Routing Table was specified. Exiting.'); | |
return false; | |
} | |
/* | |
Save the original log level so we can revert back to this when exiting the Controller. | |
*/ | |
$originalLogLevel = $modx->getLogLevel(); | |
if($debugmode){ | |
$modx->setLogLevel(modX::LOG_LEVEL_DEBUG); | |
} | |
if(!$requestObject){ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error getting SimplxRequest object.'); | |
return false; | |
} | |
if(!$parseError){ | |
/* | |
Get the JSON serialized routing table | |
*/ | |
$routingTableObject = $modx->cacheManager->get($routingtable); | |
if(!$routingTableObject){ | |
$routingTableObject = $modx->getObject('modChunk',array('name' => $routingtable )); | |
$routingTableObject = $routingTableObject->getContent(); | |
$modx->cacheManager->set($routingtable,$routingTableObject); | |
} | |
$routingTableError = false; | |
$routingTableLookupError = false; | |
try{ | |
$routingTableObject = json_decode($routingTableObject,true); | |
/* | |
Get initial request scope to parse (path,uri,cookie,header,query,form etc) | |
First, check the if we have a Snippet parameter to use. | |
*/ | |
if(!$routingconstraint || $routingconstraint == ''){ | |
/* | |
No routing constraint parameter was passed to us, so lets look for a default instruction in the routing table. | |
*/ | |
if(array_key_exists('routingconstraint',$routingTableObject)){ | |
$routingconstraint = $routingTableObject['routingconstraint']; | |
}else{ | |
//$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error, no routing constraint was specified.'); | |
//return false; | |
$routingconstraint = null; | |
} | |
} | |
/* | |
Get the contexts collection from the decoded array | |
*/ | |
$routingTableObject = $routingTableObject['contexts']; | |
$routingTableError = false; | |
}catch(Exception $e){ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error loading routing table.'); | |
return false; | |
} | |
if(!$routingTableError){ | |
$routingContextKey = $modx->context->key; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, '----------------------------------------------------------'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Starting the Controller. Using Routing Table "'.$routingtable.'", Constraint "'.$routingconstraint.'", Field Delimiter "'.$fielddelimiter.'" and Value Delimiter "'.$valuedelimiter.'".'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Using "'.$defaultconstrainttoken.'" as default constraint.'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Checking if the current MODx Context "'.$routingContextKey.'" is included in the Routing Table.'); | |
/* | |
Check if the routing table has any instructions for the current context. | |
*/ | |
if(array_key_exists($routingContextKey,$routingTableObject)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Checking if the current MODx Context "'.$routingContextKey.'" has any rules for constraint "'.$routingconstraint.'".'); | |
/* | |
Ok the Context is in the routing table. Get the actual context array. | |
*/ | |
$routingContext = $routingTableObject[$routingContextKey]; | |
if(count($routingContext)<1){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The Context "'.$routingContextKey.'" is in the Routing Table but has no rules. Exiting Controller.'); | |
return true; | |
} | |
/* | |
Get the initial item using the default constraint (path, form, query, cookie, header etc) | |
*/ | |
/* | |
If we have no default routing constraint we simply use the first constraint in the context. | |
*/ | |
if(!isset($routingconstraint)){ | |
$routingconstraint = array_keys($routingContext['constraints']); | |
$routingconstraint = $routingconstraint[0]; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: We have no default routing constraint so we use the first constraint in the context "'.$routingconstraint.'".'); | |
} | |
$routingConstraintField = SimplxRequest::lookup($routingconstraint); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Got the following result from the constraint lookup: "'.$routingConstraintField.'".'); | |
if(is_array($routingConstraintField)){ | |
/* | |
The location is an array which means that we will be looking for a routing instruction in the | |
table which is equal to the value of the constraint; i.e, if the constraint is "headers" we can | |
expect to find something like this in the table : | |
"header":{ | |
"my-header":"mysnippet" | |
} | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The constraint "'.$routingconstraint.'" is a collection of routes.'); | |
$defaultconstrainttoken = $defaultruletoken; | |
}else{ | |
/* | |
We now add the default constraint as a prefix to the result of the lookup and try to find this entry | |
in the routing table. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The constraint "'.$routingconstraint.'" is a one dimensional request field.'); | |
/* | |
The constraints in the table can be expressed as paths, or, as paths with a specified request field, i.e. | |
"headers:content-type>application/soap+xml". This is however overridden if the routing table has a path-only | |
constraint "headers:content-type". | |
*/ | |
if(!array_key_exists($routingconstraint,$routingContext['constraints'])){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Using "'.$routingconstraint.'" plus field "'.$routingConstraintField.'" as constraint.'); | |
$defaultconstrainttoken = ($routingconstraint.$valuedelimiter.$defaultruletoken); | |
$routingconstraint = ($routingconstraint.$valuedelimiter.$routingConstraintField); | |
}else{ | |
$defaultconstrainttoken = $defaultruletoken; | |
} | |
} | |
/* | |
Check if the Context has any instructions for the constraint. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Check if the Context has any rules for the constraint.'); | |
if(isset($routingConstraintField) && (array_key_exists($routingconstraint,$routingContext['constraints']) || array_key_exists($defaultconstrainttoken,$routingContext['constraints']))){ | |
// Mental note: Remove bad code below asap. | |
if(array_key_exists($routingconstraint,$routingContext['constraints'])){ | |
/* | |
Ok theres a routing instructions for the constraint. Now we get all the | |
rule the constraint. | |
*/ | |
$constraintRoutingRules = $routingContext['constraints'][$routingconstraint]; | |
/* | |
If the $constraintRoutingRules variable is not an array this means that there is only *one* | |
rule for the constraint and that the variable actually contains an instruction. | |
This means that we can run it and exit. | |
*/ | |
if(!is_array($constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The constraint had only one single rule/instruction "'.$constraintRoutingRules.'". Running Snippet and exiting.'); | |
$modx->runSnippet($constraintRoutingRules,array()); | |
return true; | |
} | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Ok there are routing rules for constraint "'.$routingconstraint.'"'); | |
/* | |
Go through the $requestObject object and look for instructions for each parameter | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Lets go through the rules to see if we find a match.'); | |
foreach ($constraintRoutingRules['rules'] as $rule => $conditions) { | |
/* | |
Look if there is a name match for the current request parameter in the | |
current location list | |
*/ | |
/* | |
If the key is the default action for the rule, we skip it til later in case we dont find any other match. | |
*/ | |
if($rule != $defaultruletoken){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The matching rule is now "'.$rule.'". Lets check for possible conditions.'); | |
$requestRuleMatch = SimplxRequest::lookup($rule); | |
if($requestRuleMatch){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The conditions for rule "'.$rule.'" is "'.$requestRuleMatch.'"'); | |
if(is_array($conditions)){ | |
// Get the actual conditions which are located in a nested array | |
$conditions = $conditions['conditions']; | |
/* | |
For each parameter there can be different values which in turn have different | |
routing instructions in the location list. | |
Lets search for a value match. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There are instructions for the rule "'.$rule.'", lets look for a match to "'.$requestRuleMatch.'".'); | |
//if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'This is the collection of instructions for this rule: "'.json_encode($instructions).'".'); | |
$ruleInstruction = $conditions[$requestRuleMatch]; | |
/* | |
Check if there was a valid instruction present | |
*/ | |
if($ruleInstruction != ""){ | |
/* | |
Good lets run the Snippet which was in the instruction and exit | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a matching instruction for rule "'.$rule.'" condition "'.$requestRuleMatch.'".'); | |
if(is_array($ruleInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($ruleInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$ruleInstruction[0].'" for "'.$rule.'", then exiting.'); | |
$result = $modx->runSnippet($ruleInstruction[0],$ruleInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$ruleInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($ruleInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
/* | |
No instruction was specified for this rule. Lets look and | |
see if there is a default instruction. The default instruction is has a key of '*'. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no instruction for rule "'.$requestRuleMatch.'". Checking default.'); | |
$defaultInstruction = $conditions[$defaultruletoken]; | |
if($defaultInstruction != ""){ | |
/* | |
Good lets run the Snippet which was in the default instruction and exit | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'A default instruction was found for rule "'.$rule.'".'); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
//$modx->runSnippet($defaultInstruction); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching instruction or default was found for rule "'.$rule.'". Exiting.'); | |
return true; | |
} // if($defaultInstruction != "") | |
} // if($ruleInstruction != "") | |
}else{ | |
/* | |
There was only one single instruction for this rule. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was only one single instruction for rule "'.$rule.'". Running "'.$conditions.'"'); | |
$modx->runSnippet($conditions); | |
return true; | |
} //if(is_array($conditions)) | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No condition was found for the rule "'.$rule.'".'); | |
} // if($requestRuleMatch) | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default rule that we might use.'); | |
} //if($rule != $defaultconstrainttoken) | |
} // End of foreach | |
/* | |
If we got this far we have a default rule for the constraint to check out. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching rule was found. Lets look for a default instruction for the default constraint'); | |
/* | |
If we got this far, lets look for the instruction for the default constraint | |
*/ | |
$constraintDefaultRules = $constraintRoutingRules['rules'][$defaultruletoken]; | |
if(is_array($constraintDefaultRules)){ | |
if(array_key_exists($defaultruletoken,$constraintDefaultRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default instruction for the default constraint: "'.json_encode($constraintDefaultRules)); | |
$defaultInstruction = $constraintDefaultRules[$defaultruletoken]; | |
if($defaultInstruction){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default instruction for constraint:'.$routingConstraint); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no default action for "'.$routingconstraint.'"'); | |
return true; | |
} | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default action "'.$constraintDefaultRules.'" for constraint:'.$routingconstraint); | |
$modx->runSnippet($constraintDefaultRules); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching rule was found. Lets look for a default instruction for the default constraint'); | |
/* | |
If we got this far, lets look for the instruction for the default constraint | |
*/ | |
$constraintRoutingRules = $routingContext['constraints'][$defaultconstrainttoken]; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, json_encode($constraintRoutingRules)); | |
if(is_array($constraintRoutingRules)){ | |
if(array_key_exists($defaultconstrainttoken,$constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default instruction for the default constraint: "'.json_encode($constraintRoutingRules)); | |
$defaultInstruction = $constraintRoutingRules[$defaultconstrainttoken]; | |
if($defaultInstruction){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default action "'.$defaultInstruction.'" for constraint:'.$routingConstraint); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no default instruction for "'.$routingconstraint.'"'); | |
return true; | |
} | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default instruction "'.$constraintRoutingRules.'" for constraint:'.$routingconstraint); | |
if(is_array($constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($constraintRoutingRules[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($constraintRoutingRules[0],$constraintRoutingRules[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($constraintRoutingRules,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
} | |
} // if(array_key_exists($routingconstraint,$routingContext) | |
}else{ | |
/* | |
Check for a default instruction for the current context | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Looking for default instruction for the Context.'); | |
if(array_key_exists($defaultruletoken,$routingContext['constraints'])){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found default instruction for the Context.'); | |
$defaultRules = $routingContext['constraints'][$defaultruletoken]; | |
if(is_array($defaultRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Got more than one Rule "'.json_encode($defaultRules).'".'); | |
/* | |
Check if theres a default condition for the default rule. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultRules[1]).'". Running Snippet "'.$$defaultRules[0].'".'); | |
$defaultInstruction = $defaultRules[$defaultruletoken]; | |
$result = $modx->runSnippet($defaultRules[0],$defaultRules[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
/* | |
if(array_key_exists($defaultruletoken,$defaultRules)){ | |
$defaultInstruction = $defaultRules[$defaultruletoken]; | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
*/ | |
}else{ | |
/* | |
If the default Rule is not an Array, we can assume that its really an Instruction. | |
*/ | |
if($defaultRules){ | |
$defaultInstruction = $defaultRules; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} // if(is_array($defaultInstruction)) | |
} // if(is_array($defaultInstruction)) | |
}else{ | |
return; | |
} // if(array_key_exists('*',$routingContext)) | |
} // if(array_key_exists($routingConstraint,$routingContext)) | |
}else{ | |
return; | |
} // if(array_key_exists($routingContextKey,$routingTableObject)) | |
}else{ | |
return; | |
} //if(!$routingTableError) | |
}else{ | |
return; | |
} // if(!$parseError) | |
function simplx_controller_getRoutingTable($routingtable){ | |
global $modx; | |
$routingTableObject = $modx->cacheManager->get($routingtable); | |
if(!$routingTableObject){ | |
/* | |
Get the JSON serialized routing table | |
*/ | |
$routingTableObject = $modx->getObject('modChunk',array('name' => $routingtable )); | |
$routingTableObject = $routingTableObject->getContent(); | |
$modx->cacheManager->set($routingtable,$routingTableObject); | |
} | |
return $routingTableObject; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"name":"routingtable","desc":"*Required* This must have the name of the Chunk which serves as default Routing Table.","xtype":"textfield","options":[],"value":"simplx.controller.routingtable.rest","lexicon":null,"overridden":false,"desc_trans":"*Required* This must have the name of the Chunk which serves as default Routing Table.","menu":null},{"name":"routingconstraint","desc":"*Optional* The Routing Constraint tells the Controller which Request field to initially use as routing rule. Possible values include \"path\", \"headers\", \"cookies\", \"query\", \"form\" etc","xtype":"textfield","options":[],"value":"","lexicon":null,"overridden":false,"desc_trans":"*Optional* The Routing Constraint tells the Controller which Request field to initially use as routing rule. Possible values include \"path\", \"headers\", \"cookies\", \"query\", \"form\" etc","menu":null},{"name":"debugmode","desc":"Should the Controller output its debug log?","xtype":"combo-boolean","options":[],"value":true,"lexicon":null,"overridden":false,"desc_trans":"Should the Controller output its debug log?","menu":null},{"name":"fielddelimiter","desc":"This is the token that separates Request fields from values, ie in \"header:content-type>text/html\", \":\" is a field delimiter.","xtype":"textfield","options":[],"value":".","lexicon":null,"overridden":false,"desc_trans":"This is the token that separates Request fields from values, ie in \"header:content-type>text/html\", \":\" is a field delimiter.","menu":null},{"name":"defaultruletoken","desc":"This is the char that symbolizes the default rule for a specific constraint. This is by default '*'.","xtype":"textfield","options":[],"value":"*","lexicon":null,"overridden":false,"desc_trans":"This is the char that symbolizes the default rule for a specific constraint. This is by default '*'.","menu":null},{"name":"valuedelimiter","desc":"This is the token that separates Request fields from values, ie in \"header:content-type>text/html\", \">\" is a value delimiter.","xtype":"textfield","options":[],"value":"=","lexicon":null,"overridden":false,"desc_trans":"This is the token that separates Request fields from values, ie in \"header:content-type>text/html\", \">\" is a value delimiter.","menu":null},{"name":"patterndelimiter","desc":"","xtype":"textfield","options":[],"value":"?","lexicon":null,"overridden":false,"desc_trans":"","menu":null}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
MODx Plugin simplx_controller | |
Version 111028 | |
The SIMPLX Controller is a routing Plugin/Snippet for MODx Revolution developed by Lars C Wallin. | |
The Plugin catches the HTTP Request on for example, | |
- onWebPageInit | |
- onManagerPageInit | |
,loads a routing table specified Chunk and checks its rules to decide which Snippet to run. | |
While it's a simple enough concept, it packs great power! You can set routing rules on any information | |
contained in the HTTP Request such as header fields, url, urn, form fields, querystrings etc. | |
It's like a generic controller++ :) | |
*/ | |
/* | |
Probably not needed, but lets check so that the $scriptProperties variable isnt null. | |
*/ | |
if(!$scriptProperties){ | |
$scriptProperties = array(); | |
} | |
/* | |
Now lets call the controller Snippet. The controller will get different config options | |
from the $scriptProperties array, which in turn gets its content from the current System Event. | |
You can easily change all config by just clicking on the System Event, scrolling down to desired | |
Event, and change Property Set for that specific Event. | |
*/ | |
$modx->runSnippet('simplx.controller',$scriptProperties); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
** | |
** DEVELOPMENT VERSION - NOT FOR ANY KIND OF DEPLOYMENT! | |
** | |
*/ | |
require_once($modx->getOption('core_path').'components/simplx/request/simplx.request.php'); | |
$activeProcesses = array(); | |
$parseError = false; | |
$routingTableObject = isset($routingTableObject) ? $routingTableObject : false; | |
$requestObject = isset($requestObject) ? $requestObject : SimplxRequest::getRequest(); | |
$fielddelimiter = isset($fielddelimiter) ? $fielddelimiter : '.'; | |
$valuedelimiter = isset($valuedelimiter) ? $valuedelimiter : '='; | |
$patterndelimiter = isset($patterndelimiter) ? $patterndelimiter : '?'; | |
$routingConstraintField = ''; | |
$constraintRoutingRules = ''; | |
$defaultruletoken = isset($defaultruletoken) ? $defaultruletoken : '*'; | |
$defaultconstrainttoken = isset($defaultconstrainttoken) ? $defaultconstrainttoken : '*'; | |
SimplxRequest::$fieldDelimiter = $fielddelimiter; | |
SimplxRequest::$valueDelimiter = $valuedelimiter; | |
/* | |
Save the original log level so we can revert back to this when exiting the Controller. | |
*/ | |
$originalLogLevel = $modx->getLogLevel(); | |
if($debugmode){ | |
$modx->setLogLevel(modX::LOG_LEVEL_DEBUG); | |
} | |
if(!$requestObject){ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error getting SimplxRequest object.'); | |
return false; | |
} | |
if(!$parseError){ | |
/* | |
Get the JSON serialized routing table | |
*/ | |
simplx_controller_getRoutingTable($routingtable); | |
/* | |
$routingTableObject = $modx->cacheManager->get($routingtable); | |
if(!$routingTableObject){ | |
$routingTableObject = $modx->getObject('modChunk',array('name' => $routingtable )); | |
$routingTableObject = $routingTableObject->getContent(); | |
$modx->cacheManager->set($routingtable,$routingTableObject); | |
} | |
$routingTableError = false; | |
$routingTableLookupError = false; | |
*/ | |
if($routingTableObject){ | |
//$routingTableObject = json_decode($routingTableObject,true); | |
/* | |
Get initial request scope to parse (path,uri,cookie,header,query,form etc) | |
First, check the if we have a Snippet parameter to use. | |
*/ | |
if(!$routingconstraint || $routingconstraint == ''){ | |
/* | |
No routing constraint parameter was passed to us, so lets look for a default instruction in the routing table. | |
*/ | |
if(array_key_exists('routingconstraint',$routingTableObject)){ | |
$routingconstraint = $routingTableObject['routingconstraint']; | |
}else{ | |
//$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error, no routing constraint was specified.'); | |
//return false; | |
$routingconstraint = null; | |
} | |
} | |
/* | |
Get the contexts collection from the decoded array | |
*/ | |
$routingTableObject = $routingTableObject['contexts']; | |
$routingTableError = false; | |
}else{ | |
$modx->log(modX::LOG_LEVEL_ERROR, 'SIMPLX_Controller: Error loading routing table.'); | |
return false; | |
} | |
if(!$routingTableError){ | |
$routingContextKey = $modx->context->key; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, '----------------------------------------------------------'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Starting the Controller. Using Routing Table "'.$routingtable.'", Constraint "'.$routingconstraint.'", Field Delimiter "'.$fielddelimiter.'" and Value Delimiter "'.$valuedelimiter.'".'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Using "'.$defaultconstrainttoken.'" as default constraint.'); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Checking if the current MODx Context "'.$routingContextKey.'" is included in the Routing Table.'); | |
/* | |
Check if the routing table has any instructions for the current context. | |
*/ | |
$routingContext = simplx_routingTable_getContext($routingContextKey); | |
if($routingContext){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Checking if the current MODx Context "'.$routingContextKey.'" has any rules for constraint "'.$routingconstraint.'".'); | |
if(count($routingContext)<1){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The Context "'.$routingContextKey.'" is in the Routing Table but has no rules. Exiting Controller.'); | |
return true; | |
} | |
/* | |
Get the initial item using the default constraint (path, form, query, cookie, header etc) | |
*/ | |
/* | |
If we have no default routing constraint we simply use the first constraint in the context. | |
*/ | |
if(!isset($routingconstraint)){ | |
$routingconstraint = array_keys($routingContext['constraints']); | |
$routingconstraint = $routingconstraint[0]; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: We have no default routing constraint so we use the first constraint in the context "'.$routingconstraint.'".'); | |
} | |
$routingConstraintField = SimplxRequest::lookup($routingconstraint); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Got the following result from the constraint lookup: "'.$routingConstraintField.'".'); | |
if(is_array($routingConstraintField)){ | |
/* | |
The location is an array which means that we will be looking for a routing instruction in the | |
table which is equal to the value of the constraint; i.e, if the constraint is "headers" we can | |
expect to find something like this in the table : | |
"header":{ | |
"my-header":"mysnippet" | |
} | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The constraint "'.$routingconstraint.'" is a collection of routes.'); | |
$defaultconstrainttoken = $defaultruletoken; | |
}else{ | |
/* | |
We now add the default constraint as a prefix to the result of the lookup and try to find this entry | |
in the routing table. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: The constraint "'.$routingconstraint.'" is a one dimensional request field.'); | |
/* | |
The constraints in the table can be expressed as paths, or, as paths with a specified request field, i.e. | |
"headers:content-type>application/soap+xml". This is however overridden if the routing table has a path-only | |
constraint "headers:content-type". | |
*/ | |
if(!array_key_exists($routingconstraint,$routingContext['constraints'])){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Using "'.$routingconstraint.'" plus field "'.$routingConstraintField.'" as constraint.'); | |
$defaultconstrainttoken = ($routingconstraint.$valuedelimiter.$defaultruletoken); | |
$routingconstraint = ($routingconstraint.$valuedelimiter.$routingConstraintField); | |
}else{ | |
$defaultconstrainttoken = $defaultruletoken; | |
} | |
} | |
/* | |
Check if the Context has any instructions for the constraint. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'SIMPLX_Controller: Check if the Context has any rules for the constraint.'); | |
if(isset($routingConstraintField) && (array_key_exists($routingconstraint,$routingContext['constraints']) || array_key_exists($defaultconstrainttoken,$routingContext['constraints']))){ | |
// Mental note: Remove bad code below asap. | |
if(array_key_exists($routingconstraint,$routingContext['constraints'])){ | |
/* | |
Ok theres a routing instructions for the constraint. Now we get all the | |
rule the constraint. | |
*/ | |
$constraintRoutingRules = $routingContext['constraints'][$routingconstraint]; | |
/* | |
If the $constraintRoutingRules variable is not an array this means that there is only *one* | |
rule for the constraint and that the variable actually contains an instruction. | |
This means that we can run it and exit. | |
*/ | |
if(!is_array($constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The constraint had only one single rule/instruction "'.$constraintRoutingRules.'". Running Snippet and exiting.'); | |
$modx->runSnippet($constraintRoutingRules,array()); | |
return true; | |
} | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Ok there are routing rules for constraint "'.$routingconstraint.'"'); | |
/* | |
Go through the $requestObject object and look for instructions for each parameter | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Lets go through the rules to see if we find a match.'); | |
foreach ($constraintRoutingRules['rules'] as $rule => $conditions) { | |
/* | |
Look if there is a name match for the current request parameter in the | |
current location list | |
*/ | |
/* | |
If the key is the default action for the rule, we skip it til later in case we dont find any other match. | |
*/ | |
if($rule != $defaultruletoken){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The matching rule is now "'.$rule.'". Lets check for possible conditions.'); | |
$requestRuleMatch = SimplxRequest::lookup($rule); | |
if($requestRuleMatch){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The conditions for rule "'.$rule.'" is "'.$requestRuleMatch.'"'); | |
if(is_array($conditions)){ | |
// Get the actual conditions which are located in a nested array | |
$conditions = $conditions['conditions']; | |
/* | |
For each parameter there can be different values which in turn have different | |
routing instructions in the location list. | |
Lets search for a value match. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There are instructions for the rule "'.$rule.'", lets look for a match to "'.$requestRuleMatch.'".'); | |
//if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'This is the collection of instructions for this rule: "'.json_encode($instructions).'".'); | |
$ruleInstruction = $conditions[$requestRuleMatch]; | |
/* | |
Check if there was a valid instruction present | |
*/ | |
if($ruleInstruction != ""){ | |
/* | |
Good lets run the Snippet which was in the instruction and exit | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a matching instruction for rule "'.$rule.'" condition "'.$requestRuleMatch.'".'); | |
if(is_array($ruleInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($ruleInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$ruleInstruction[0].'" for "'.$rule.'", then exiting.'); | |
$result = $modx->runSnippet($ruleInstruction[0],$ruleInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$ruleInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($ruleInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
/* | |
No instruction was specified for this rule. Lets look and | |
see if there is a default instruction. The default instruction is has a key of '*'. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no instruction for rule "'.$requestRuleMatch.'". Checking default.'); | |
$defaultInstruction = $conditions[$defaultruletoken]; | |
if($defaultInstruction != ""){ | |
/* | |
Good lets run the Snippet which was in the default instruction and exit | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'A default instruction was found for rule "'.$rule.'".'); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
//$modx->runSnippet($defaultInstruction); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching instruction or default was found for rule "'.$rule.'". Exiting.'); | |
return true; | |
} // if($defaultInstruction != "") | |
} // if($ruleInstruction != "") | |
}else{ | |
/* | |
There was only one single instruction for this rule. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was only one single instruction for rule "'.$rule.'". Running "'.$conditions.'"'); | |
$modx->runSnippet($conditions); | |
return true; | |
} //if(is_array($conditions)) | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No condition was found for the rule "'.$rule.'".'); | |
} // if($requestRuleMatch) | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default rule that we might use.'); | |
} //if($rule != $defaultconstrainttoken) | |
} // End of foreach | |
/* | |
If we got this far we have a default rule for the constraint to check out. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching rule was found. Lets look for a default instruction for the default constraint'); | |
/* | |
If we got this far, lets look for the instruction for the default constraint | |
*/ | |
$constraintDefaultRules = $constraintRoutingRules['rules'][$defaultruletoken]; | |
if(is_array($constraintDefaultRules)){ | |
if(array_key_exists($defaultruletoken,$constraintDefaultRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default instruction for the default constraint: "'.json_encode($constraintDefaultRules)); | |
$defaultInstruction = $constraintDefaultRules[$defaultruletoken]; | |
if($defaultInstruction){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default instruction for constraint:'.$routingConstraint); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no default action for "'.$routingconstraint.'"'); | |
return true; | |
} | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default action "'.$constraintDefaultRules.'" for constraint:'.$routingconstraint); | |
$modx->runSnippet($constraintDefaultRules); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'No matching rule was found. Lets look for a default instruction for the default constraint'); | |
/* | |
If we got this far, lets look for the instruction for the default constraint | |
*/ | |
$constraintRoutingRules = $routingContext['constraints'][$defaultconstrainttoken]; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, json_encode($constraintRoutingRules)); | |
if(is_array($constraintRoutingRules)){ | |
if(array_key_exists($defaultconstrainttoken,$constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found a default instruction for the default constraint: "'.json_encode($constraintRoutingRules)); | |
$defaultInstruction = $constraintRoutingRules[$defaultconstrainttoken]; | |
if($defaultInstruction){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default action "'.$defaultInstruction.'" for constraint:'.$routingConstraint); | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'There was no default instruction for "'.$routingconstraint.'"'); | |
return true; | |
} | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Running default instruction "'.$constraintRoutingRules.'" for constraint:'.$routingconstraint); | |
if(is_array($constraintRoutingRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($constraintRoutingRules[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($constraintRoutingRules[0],$constraintRoutingRules[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($constraintRoutingRules,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
} | |
} // if(array_key_exists($routingconstraint,$routingContext) | |
}else{ | |
/* | |
Check for a default instruction for the current context | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Looking for default instruction for the Context.'); | |
if(array_key_exists($defaultruletoken,$routingContext['constraints'])){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Found default instruction for the Context.'); | |
$defaultRules = $routingContext['constraints'][$defaultruletoken]; | |
if(is_array($defaultRules)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'Got more than one Rule "'.json_encode($defaultRules).'".'); | |
/* | |
Check if theres a default condition for the default rule. | |
*/ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultRules[1]).'". Running Snippet "'.$$defaultRules[0].'".'); | |
$defaultInstruction = $defaultRules[$defaultruletoken]; | |
$result = $modx->runSnippet($defaultRules[0],$defaultRules[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
/* | |
if(array_key_exists($defaultruletoken,$defaultRules)){ | |
$defaultInstruction = $defaultRules[$defaultruletoken]; | |
if(is_array($defaultInstruction)){ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has default parameters "'.json_encode($defaultInstruction[1]).'" condition "'.$requestRuleMatch.'". Running Snippet "'.$defaultInstruction[0].'".'); | |
$result = $modx->runSnippet($defaultInstruction[0],$defaultInstruction[1]); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
}else{ | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} | |
*/ | |
}else{ | |
/* | |
If the default Rule is not an Array, we can assume that its really an Instruction. | |
*/ | |
if($defaultRules){ | |
$defaultInstruction = $defaultRules; | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction has no default parameters. Running Snippet "'.$defaultInstruction.'", then exiting.'); | |
$result = $modx->runSnippet($defaultInstruction,array()); | |
if($debugmode) $modx->log(modX::LOG_LEVEL_DEBUG, 'The instruction returned "'.json_encode($result).'"'); | |
return true; | |
} // if(is_array($defaultInstruction)) | |
} // if(is_array($defaultInstruction)) | |
}else{ | |
return; | |
} // if(array_key_exists('*',$routingContext)) | |
} // if(array_key_exists($routingConstraint,$routingContext)) | |
}else{ | |
return; | |
} // if(array_key_exists($routingContextKey,$routingTableObject)) | |
}else{ | |
return; | |
} //if(!$routingTableError) | |
}else{ | |
return; | |
} // if(!$parseError) | |
function simplx_controller_parseContext($context){ | |
global $modx; | |
} | |
function simplx_controller_parseConstraint($constraint){ | |
global $modx; | |
} | |
function simplx_controller_parseRule($rule){ | |
global $modx; | |
} | |
function simplx_controller_parseCondition($condition){ | |
global $modx; | |
} | |
function simplx_controller_parseInstruction($instruction){ | |
global $modx; | |
} | |
function simplx_controller_setRoutingTable($table){ | |
global $modx; | |
} | |
function simplx_controller_setRequestMessage($request){ | |
global $modx; | |
} | |
function simplx_routingTable_getContext($contextName){ | |
global $modx; | |
if(array_key_exists($contextName,$routingTableObject)){ | |
/* | |
Ok the Context is in the routing table. Get the actual context array. | |
*/ | |
$routingContext = $routingTableObject[$contextName]; | |
}else{ | |
return false; | |
} | |
} | |
function simplx_controller_getRoutingTable($routingtable){ | |
global $modx; | |
$routingTableObject = $modx->cacheManager->get($routingtable); | |
if(!$routingTableObject){ | |
/* | |
Get the JSON serialized routing table | |
*/ | |
$routingTableObject = $modx->getObject('modChunk',array('name' => $routingtable )); | |
$routingTableObject = $routingTableObject->getContent(); | |
$modx->cacheManager->set($routingtable,$routingTableObject); | |
} | |
$routingTableError = false; | |
$routingTableLookupError = false; | |
$routingTableObject = json_decode($routingTableObject,true); | |
if($routingTableObject){ | |
return $routingTableObject; | |
}else{ | |
return false; | |
} | |
} | |
class simplxRoutingTable{ | |
private $state; | |
protected $contexts = array(); | |
protected $initialConstraint; | |
protected $name; | |
protected $routingTableObject; | |
protected $fielddelimiter; | |
protected $valuedelimiter; | |
protected $patterndelimiter; | |
protected $routingConstraintField; | |
protected $constraintRoutingRules; | |
protected $defaultruletoken; | |
protected $defaultconstrainttoken; | |
public function _construct($routingtable = null){ | |
global $modx; | |
if(isset($routingtable)){ | |
if(is_array($routingtable)){ | |
$this->state = $routingtable; | |
$this->contexts = $this->state['contexts']; | |
/* | |
Check if the state is valid. It should always have at least one Constraint | |
*/ | |
if(!$this->contexts){ | |
return false; | |
} | |
$this->initialConstraint = $this->state['initialconstraint'] ? $this->state['initialconstraint'] : ''; | |
$this->name = $this->state['name'] ? $this->routingTableObject['name'] : ''; | |
$this->fieldDelimiter = isset($this->state['fielddelimiter']) ? $this->state['fielddelimiter'] : '.'; | |
$this->valueDelimiter = isset($this->state['valuedelimiter']) ? $this->state['valuedelimiter'] : '='; | |
$this->patternDelimiter = isset($this->state['patterndelimiter']) ? $this->state['patterndelimiter'] : '?'; | |
$this->defaultRuleToken = isset($this->state['$defaultruletoken']) ? $this->state['$defaultruletoken'] : '*'; | |
$this->defaultConstraintToken = isset($this->state['defaultconstrainttoken']) ? $this->state['defaultconstrainttoken'] : '*'; | |
}else{ | |
$routingTableObject = $modx->cacheManager->get($routingtable); | |
if(!$routingTableObject){ | |
/* | |
Get the JSON serialized routing table | |
*/ | |
$$this->state = $modx->getObject('modChunk',array('name' => $routingtable )); | |
$this->state = $routingTableObject->getContent(); | |
$modx->cacheManager->set($routingtable,$this->state); | |
} | |
$this->state = json_decode($routingtable,true); | |
/* | |
Check so that the $routingTableObject was decoded to a valid php array. | |
*/ | |
if(is_array($this->state)){ | |
$this->contexts = $this->state['contexts']; | |
/* | |
Check if the state is valid. It should always have at least one Constraint | |
*/ | |
if(!$this->contexts){ | |
return false; | |
} | |
$this->initialConstraint = $this->state['initialconstraint'] ? $this->state['initialconstraint'] : ''; | |
$this->name = $this->state['name'] ? $this->routingTableObject['name'] : ''; | |
$this->fieldDelimiter = isset($this->state['fielddelimiter']) ? $this->state['fielddelimiter'] : '.'; | |
$this->valueDelimiter = isset($this->state['valuedelimiter']) ? $this->state['valuedelimiter'] : '='; | |
$this->patternDelimiter = isset($this->state['patterndelimiter']) ? $this->state['patterndelimiter'] : '?'; | |
$this->defaultRuleToken = isset($this->state['$defaultruletoken']) ? $this->state['$defaultruletoken'] : '*'; | |
$this->defaultConstraintToken = isset($this->state['defaultconstrainttoken']) ? $this->state['defaultconstrainttoken'] : '*'; | |
// So far so good | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
} | |
} | |
/* | |
Context related methods | |
*/ | |
public function getContext($name){ | |
if(isset($name)){ | |
} | |
} | |
public function setContext($value){ | |
if(isset($value)){ | |
} | |
} | |
public function saveContext($state){ | |
if(isset($state)){ | |
} | |
} | |
public function deleteContext($name){ | |
if(isset($name)){ | |
} | |
} | |
public function getContexts(){ | |
} | |
public function save($name){ | |
/* | |
The $name argument makes it possible to "save as" or clone. | |
*/ | |
if(isset($name)){ | |
} | |
} | |
} | |
class simplxRoutingCondition{ | |
private $state; | |
public function _construct($state = null){ | |
global $modx; | |
if(isset($state)){ | |
if(is_array($state)){ | |
$this->state = $state; | |
//$this->contexts = $this->state['contexts']; | |
/* | |
Check if the state is valid. It should always have at least one Constraint | |
*/ | |
if(!$this->contexts){ | |
return false; | |
} | |
//$this->initialConstraint = $this->state['initialconstraint'] ? $this->state['initialconstraint'] : ''; | |
}else{ | |
$this->state = json_decode($state,true); | |
/* | |
Check so that the $routingTableObject was decoded to a valid php array. | |
*/ | |
if(is_array($this->state)){ | |
/* | |
Check if the state is valid. It should always have at least one Constraint | |
*/ | |
if(!$this->contexts){ | |
return false; | |
} | |
$this->key = $this->state[0]; | |
// So far so good | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
} | |
} | |
/* | |
Context related methods | |
*/ | |
public function getContext($name){ | |
if(isset($name)){ | |
} | |
} | |
public function setContext($value){ | |
if(isset($value)){ | |
} | |
} | |
public function saveContext($state){ | |
if(isset($state)){ | |
} | |
} | |
public function deleteContext($name){ | |
if(isset($name)){ | |
} | |
} | |
public function getContexts(){ | |
} | |
public function save($name){ | |
/* | |
The $name argument makes it possible to "save as" or clone. | |
*/ | |
if(isset($name)){ | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Larsc,
Do you have the complete simplx.controller (0.8.0-beta4) package on github anywhere. I have made a slight adjustment to the latest source code version to allow for a (*) wildcard context and would like to place a pull request.