function modelResources($dir, $modelDir, &$allTags) { // the models are added to the Controller super object by the loader foreach (glob($modelDir . DIRECTORY_SEPARATOR . '*.php') as $modelFile) { $key = basename($modelFile, '.php'); $propertyType = ucfirst($key); // the property name will NOT have the prefix $propertyName = strtolower($key); $allTags[] = Triumph_DetectedTag::CreateMember('CI_Controller', $propertyName, $propertyType); } // models can be located in sub-directories need to recurse down sub-dirs $dirId = opendir($modelDir); if ($dirId) { $item = readdir($dirId); while ($item !== FALSE) { // ignore the parent dir, also any hidden dirs if ($item != '.' && $item != '..' && !substr($item, 0, 1) != '.') { $modelSubDir = $modelDir . DIRECTORY_SEPARATOR . $item; if (is_dir($modelSubDir)) { modelResources($dir, $modelSubDir, $allTags); } } $item = readdir($dirId); } } closedir($dirId); }
/** * * @param string $sourceDir the root directory of the project in question * @param string $resourceDbFileName 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 URLs for the given source directory; this situation * is different than zero URLs being detected. * @return Triumph_Resource[] array of Triumph_Resource instances the detected tags */ function detectTags($sourceDir, $resourceDbFileName, &$doSkip) { $allTags = array(); if (!is_file($resourceDbFileName)) { return $allTags; } // 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 tags from the previous detection script // from being deleted. $doSkip = TRUE; // for laravel, we look for the artisan script. if we don't have the artisan script assume // that this source is not a laravel project. $sourceDir = \opstring\ensure_ends_with($sourceDir, DIRECTORY_SEPARATOR); if (!is_file($sourceDir . 'artisan')) { return $allTags; } $doSkip = FALSE; // get all of the configured aliases, laravel automatically imports // certain classes into the root namespace. // load the laravel bootstrap $bootstrapFile = $sourceDir . 'bootstrap' . DIRECTORY_SEPARATOR . 'autoload.php'; $startFile = $sourceDir . 'bootstrap' . DIRECTORY_SEPARATOR . 'start.php'; if (is_file($bootstrapFile) && is_file($startFile)) { require $bootstrapFile; $app = (require_once $startFile); // laravel defines a set of aliases that get added in to the // root namespace at run-time. we loop through the aliases // and add a method with the class name being the alias name // and the method name being the method from the class being // aliased $pdo = Zend_Db::factory('Pdo_Sqlite', array("dbname" => $resourceDbFileName)); $resourceTable = new Triumph_ResourceTable($pdo); // I want to read the aliases from the config, but unfortunately // we need more info. laravel facades work in this manner: // facade => ioc key => class name // the config gives us the facade names, but the ioc keys are hidden in the // facade. // for now, we extract the default ioc keys from the Application // the default aliases, IOC keys, and classes are in // laravel/framework/src/Illuminate/Foundation/Application.php // ideally, we should be able to find "bind" calls in the service // providers $arrDefaultAliases = defaultAliases(); $arrIocKeyToFacade = defaultBindings(); foreach ($arrDefaultAliases as $strIocKey => $strFullClassName) { // the full names in the laravel config file do not start // with the root namespace, but we want Triumph to know // that these are fully qualified class names $strFullClassName = \opstring\ensure_begins_with($strFullClassName, '\\'); $strParent = get_parent_class($strFullClassName); $strAlias = $arrIocKeyToFacade[$strIocKey]; // if the alias is a facade, get the methods of the facade class that is // being adapted // the facade is created by asking the app for a $arrResources = $resourceTable->FindPublicMethodsMembersForClass($strFullClassName, $sourceDir); foreach ($arrResources as $resource) { if (Triumph_Resource::TYPE_METHOD == $resource->type) { $detectedTag = Triumph_DetectedTag::CreateMethod($strAlias, $resource->identifier, $resource->returnType, '\\', $resource->comment); // set the member as being static // laravel implements facades using the __callStatic // magic method // since triumph is smart enough to only show static methods // when a static call is being made, we must set the static flag // to true, else code completion will not work $detectedTag->isStatic = TRUE; $detectedTag->signature = $resource->signature; $allTags[] = $detectedTag; } else { if (Triumph_Resource::TYPE_MEMBER == $resource->type) { $detectedTag = Triumph_DetectedTag::CreateMember($strAlias, $resource->identifier, $resource->returnType, '\\', $resource->comment); $detectedTag->signature = $resource->signature; $detectedTag->isStatic = TRUE; $allTags[] = $detectedTag; } } } } } return $allTags; }