/**
 * This function will use the resource cache to lookup all controllers and their methods.  Then it
 * will create a Triumph_Url instance for each method; note that the routes file is 
 * also consulted and we will generate URLs for the default controller.
 *
 * @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  string  $host                 the hostname of the application; this will be used a the prefix on all URLs
 * @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_Url[]               array of Triumph_Url instances the detected URLs
 */
function detectUrls($sourceDir, $resourceDbFileName, $host, &$doSkip)
{
    $doSkip = TRUE;
    if (!is_file($resourceDbFileName)) {
        return array();
    }
    $sourceDir = \opstring\ensure_ends_with($sourceDir, DIRECTORY_SEPARATOR);
    $host = \opstring\ensure_ends_with($host, '/');
    // TODO: handle multiple apps
    // need this define so that we can include code igniter files directly
    if (!defined('BASEPATH')) {
        define('BASEPATH', '');
    }
    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 array();
    }
    $doSkip = FALSE;
    // get the code igniter configuration so that we can use it to build the
    // correct routes
    $config = array();
    $route = array();
    include $sourceDir . 'application/config/routes.php';
    include $sourceDir . 'application/config/config.php';
    $allUrls = array();
    // lookup all controller files from the resource cache, only controllers are accessible via URLs
    // since file names in the cache are OS dependant, need to use the correct directory separators
    $pdo = Zend_Db::factory('Pdo_Sqlite', array("dbname" => $resourceDbFileName));
    $fileItemTable = new Triumph_FileItemTable($pdo);
    $controllerDir = $sourceDir . 'application' . DIRECTORY_SEPARATOR . 'controllers';
    $matchingFiles = $fileItemTable->MatchingFiles($controllerDir);
    // lookup all of the methods for all controller files.
    $resourceTable = new Triumph_ResourceTable($pdo);
    $methods = $resourceTable->PublicMethodsFromFiles($matchingFiles);
    foreach ($methods as $resource) {
        // need to handle any sub-directories underneath the controllers; as the subdirectory
        // is propagated in the URL
        $controllerFile = \opstring\after($resource->fullPath, $controllerDir);
        $subDirectory = dirname($controllerFile);
        if ('\\' == $subDirectory || '/' == $subDirectory) {
            // hack to work around special case when there is no subdirectory
            $subDirectory = '';
        }
        // constructors are not web-accessible
        // code igniter makes methods that start with underscore
        if (\opstring\compare_case('__construct', $resource->identifier) && !\opstring\begins_with($resource->identifier, '_')) {
            // TODO: any controller arguments ... should get these from the user somehow
            $extra = '';
            $appUrl = makeUrl($route, $config, $subDirectory, $resource->fullPath, $resource->className, $resource->identifier, $extra);
            $appUrl->url = $host . $appUrl->url;
            $allUrls[] = $appUrl;
        }
    }
    return $allUrls;
}
 function testAfterShouldNotReturnText()
 {
     $this->assertEquals('', \opstring\after('*****@*****.**', '.com'));
     $this->assertEquals(FALSE, \opstring\after('*****@*****.**', 'csu.edu'));
 }
/**
 * This function will use the resource cache to lookup all controllers and their methods.  Then it
 * will create a Triumph_Url instance for each method; note that the routes file is 
 * also consulted and we will generate URLs for the default controller.
 *
 * @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  string $host                 the hostname of the application; this will be used a the prefix on all URLs
 * @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_UrlTag[]           array of Triumph_UrlTag instances the detected URLs
 */
function detectUrls($sourceDir, $resourceDbFileName, $host, &$doSkip)
{
    $allUrls = array();
    if (!is_file($resourceDbFileName)) {
        return $allUrls;
    }
    // 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 URLs 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 $allUrls;
    }
    $doSkip = FALSE;
    // 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);
        $app->setRequestForConsoleEnvironment();
        $artisan = Illuminate\Console\Application::start($app);
        $router = $app['router'];
        $routes = $router->getRoutes();
        foreach ($routes as $route) {
            $arr = array('host' => $route->domain(), 'uri' => $route->uri(), 'name' => $route->getName(), 'action' => $route->getActionName());
            if (!empty($route->domain())) {
                $url = $route->domain();
            } else {
                $url = $host;
            }
            $url .= $route->uri();
            // special treatment, we dont want urls to end in double slashes
            // if the route is the home route'/'
            if (\opstring\ends_with($url, '//')) {
                $url = substr($url, 0, -1);
            }
            $pos = strpos($route->getActionName(), '@');
            $className = '';
            $methodName = '';
            $fileName = '';
            if ($pos !== FALSE) {
                $className = \opstring\before($route->getActionName(), '@');
                $methodName = \opstring\after($route->getActionName(), '@');
                // find the file that the class/method are in
                $pdo = Zend_Db::factory('Pdo_Sqlite', array("dbname" => $resourceDbFileName));
                $resourceTable = new Triumph_ResourceTable($pdo);
                $allMethods = $resourceTable->FindPublicMethod($className, $methodName, $sourceDir);
                if (count($allMethods)) {
                    $fileName = $allMethods[0]->fullPath;
                }
            }
            $triumphUrl = new Triumph_UrlTag($url, $fileName, $className, $methodName);
            $allUrls[] = $triumphUrl;
        }
    }
    return $allUrls;
}