function testCompare() { $this->assertEquals(-1, \opstring\compare('that', 'this')); $this->assertEquals(0, \opstring\compare('this', 'this')); $this->assertEquals(1, \opstring\compare('this', 'that')); $this->assertEquals(1, \opstring\compare('this', 'thIS')); }
/** * This function will use the resource cache to lookup all controllers and their methods. Then it * will create a Triumph_TemplateFile instance for each method. * * @param string $sourceDir the root directory of the project in question * @param string $detectorDbFileName the location of the resource cache SQLite file; as created by Triumph * @param boolean $doSkip out parameter; if TRUE then this detector does not know how * to detect templates for the given source directory; this situation * is different than zero templates being detected. * @return Triumph_TemplateFile[] array of Triumph_TemplateFile instances the detected template files and their variables */ function detectTemplates($sourceDir, $detectorDbFileName, &$doSkip) { $doSkip = TRUE; $allTemplates = array(); if (!is_file($detectorDbFileName)) { return $allTemplates; } // need to check that this detector is able to recognize the directory structure of sourceDir // if not, then we need to skip detection by returning immediately and setting $doSkip to TRUE. // by skipping detection, we prevent any detected templates from the previous detection script // from being deleted. $sourceDir = \opstring\ensure_ends_with($sourceDir, DIRECTORY_SEPARATOR); if (!is_file($sourceDir . 'application/config/routes.php') || !is_file($sourceDir . 'application/config/config.php')) { // this source directory does not contain a code igniter directory. return $allTemplates; } $doSkip = FALSE; // add your logic here; usually it will consist of querying the SQLite database in $detectorDbFileName // recursing though the call stack and picking the method calls for templates. $pdo = Zend_Db::factory('Pdo_Sqlite', array("dbname" => $detectorDbFileName)); $callStackTable = new Triumph_CallStackTable($pdo); $callStacks = $callStackTable->load(); // figure out the variables $scopes = $callStackTable->splitScopes($callStacks); // now go through each scope, looking for calls to $this->load->view foreach ($scopes as $scope) { // list of all method calls used to find calls to view method $methodCalls = $callStackTable->getMethodCalls($scope); // list of all property accesses, make sure that calls to view method // are used on the loader member variables $propertyCalls = $callStackTable->getPropertyCalls($scope); $variableCalls = $callStackTable->getVariables($scope); foreach ($methodCalls as $destinationVariable => $call) { if (\opstring\compare_case($call->methodName, 'view') == 0 && isset($propertyCalls[$call->objectName])) { // is this view call of a loader object ? $propertyCall = $propertyCalls[$call->objectName]; if (\opstring\compare('$this', $propertyCall->objectName) == 0 && (\opstring\compare('load', $propertyCall->propertyName) == 0 || \opstring\compare('loader', $propertyCall->propertyName) == 0)) { $currentTemplate = new Triumph_TemplateFileTag(); $currentTemplate->variables = array(); $currentTemplate->fullPath = ''; if (count($call->functionArguments) >= 1) { // argument 1 of the view method call is the template file // most of the time views are given as relative relatives; starting from the application/views/ directory // for now ignore variable arguments if (isset($variableCalls[$call->functionArguments[0]])) { $variableCall = $variableCalls[$call->functionArguments[0]]; if ($variableCall->type == Triumph_CallStack::SCALAR) { $currentTemplate->fullPath = $variableCall->scalarValue; // view file may have an extension; if it has an extension use that; otherwise use the default (.php) if (stripos($currentTemplate->fullPath, '.') === FALSE) { $currentTemplate->fullPath .= '.php'; } // not using realpath() so that Triumph can know that a template file has not yet been created // or the programmer has a bug in the project. $currentTemplate->fullPath = \opstring\replace($currentTemplate->fullPath, '/', DIRECTORY_SEPARATOR); $currentTemplate->fullPath = \opstring\replace($currentTemplate->fullPath, '\\', DIRECTORY_SEPARATOR); $currentTemplate->fullPath = $sourceDir . 'application' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR . $currentTemplate->fullPath; // push it now just in case the template does not get any variables $allTemplates[] = $currentTemplate; } } } if (count($call->functionArguments) >= 2 && !empty($currentTemplate->fullPath)) { // argument 2 is an array of template variables if (isset($variableCalls[$call->functionArguments[1]])) { $variableCall = $variableCalls[$call->functionArguments[1]]; $arrayKeys = $callStackTable->getArrayKeys($scope, $variableCall->destinationVariable); foreach ($arrayKeys as $key) { // add the siguil here; editor expects us to return variables $currentTemplate->variables[] = '$' . $key; } $allTemplates[count($allTemplates) - 1] = $currentTemplate; } } } } } } return $allTemplates; }
/** * Extract all of the keys that were assigned to an array variable. * * @param array of Triumph_CallStack class the list to search in * @return array of string the array keys for the given * array variable. */ public function getArrayKeys($callStacks, $variableName) { $keys = array(); foreach ($callStacks as $call) { if (Triumph_CallStack::ARRAY_KEY == $call->type && \opstring\compare($variableName, $call->destinationVariable) == 0) { $keys[$call->arrayKey] = 1; } } return array_keys($keys); }
/** * Convenience function that checks whether haystack ends with needle. Comparison * is case-sensitive. * * @param $haystack the string to search in * @param $needle the string to search for * @return boolean TRUE if haystack begins with needle Examples: * haystack: "combo box" needle: "box" * haystack: "combo box" needle: "x" */ function ends_with($haystack, $needle) { if (strlen($needle) > strlen($haystack)) { return FALSE; } $lastPiece = substr($haystack, strlen($haystack) - strlen($needle)); return \opstring\compare($lastPiece, $needle) == 0; }
/** * Resolves the given class name - method name pair into the URL. * * @param array $route the code igniter $routes array * @param array $config the code igniter $config array * @param string $subDirectory if non-empty means that the controller is in a sub-directory of application/controllers * @param string $fileName the name of the controller file * @param string $className the name of the controller class * @param string $methodName the name of the method * @param string $extra any extra segments to append to the URL * @return Triumph_Url the full URL after routing rules have been applied. */ function makeUrl($route, $config, $subDirectory, $fileName, $className, $methodName, $extra) { // this function was taken from http://codeigniter.com/forums/viewthread/102438 // with the following changes: // 1. including routes directly instead of using CI object // as I was having problems including the bootstap file here $uri = ''; if ($subDirectory) { $uri .= $subDirectory . '/'; } $uri .= $className . '/' . $methodName; if ($extra) { $uri .= '/' . $extra; } // in case subdir has leading slash; routes usually don't $uri = ltrim($uri, '/'); $uri = strtolower($uri); if (in_array($uri, $route)) { $uri = array_search($uri, $route); } else { foreach ($route as $singleRoute => $replace) { $singleRoute = preg_split('/(\\(.+?\\))/', $singleRoute, -1, PREG_SPLIT_DELIM_CAPTURE); $replace = preg_split('/(\\$\\d+)/', $replace, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($singleRoute) != count($replace)) { continue; } $newroute = $newreplace = ''; for ($i = 0; $i < count($singleRoute); $i++) { if ($i % 2) { $newroute .= $replace[$i]; $newreplace .= $singleRoute[$i]; } else { $newroute .= $singleRoute[$i]; $newreplace .= $replace[$i]; } $newreplace = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $newreplace)); if (preg_match("#^{$newreplace}\$#", $uri)) { $uri = preg_replace("#^{$newreplace}\$#", $newroute, $uri); break; } } } } if (0 == \opstring\compare('default_controller', $uri)) { $uri = ''; } // respect the url suffix and index page from the config. for urls, make sure there is only one ending '/' // url already has leading slash // make sure url never has leading slash $indexPage = $config['index_page']; $indexPage = \opstring\ensure_ends_with($indexPage, '/'); if (!empty($uri)) { $url = $indexPage . trim($uri . '/'); $url = ltrim($url, '/'); } else { $url = ''; } if (isset($config['url_suffix']) && $config['url_suffix']) { $url .= $config['url_suffix']; } $triumphUrl = new Triumph_UrlTag($url, $fileName, $className, $methodName); return $triumphUrl; }