/** * @return Array */ public static function get_all_tests() { ManifestBuilder::load_test_manifest(); $tests = ClassInfo::subclassesFor('SapphireTest'); array_shift($tests); return $tests; }
function init() { parent::init(); if (!Permission::check('ADMIN')) { return Security::permissionFailure(); } ManifestBuilder::load_test_manifest(); }
function init() { parent::init(); ManifestBuilder::load_test_manifest(); if (!self::$default_reporter) { self::set_reporter(Director::is_cli() ? 'CliDebugView' : 'DebugView'); } }
/** * Get all available themes that haven't been marked as disabled. * @param string $baseDir Optional alternative theme base directory for testing * @return array of theme directory names */ public function getAvailableThemes($baseDir = null) { $themes = ManifestBuilder::get_themes($baseDir); foreach (self::$disabled_themes as $theme) { if (isset($themes[$theme])) { unset($themes[$theme]); } } return $themes; }
function testInterfaceDefParser() { $parser = ManifestBuilder::getInterfaceDefParser(); $tokens = $this->getTokens(); $matches = $parser->findAll($tokens); $interfaces = array(); if ($matches) { foreach ($matches as $match) { $interfaces[$match['interfaceName']] = $match; } } $this->assertArrayHasKey('InterfaceA', $interfaces); $this->assertArrayHasKey('InterfaceB', $interfaces); $this->assertEquals('Something', $interfaces['InterfaceB']['extends']); }
/** * Updates the database schema, creating tables & fields as necessary. */ function build() { // The default time limit of 30 seconds is normally not enough increase_time_limit_to(600); // Get all our classes ManifestBuilder::create_manifest_file(); require MANIFEST_FILE; if (isset($_GET['returnURL'])) { echo "<p>Setting up the database; you will be returned to your site shortly....</p>"; $this->doBuild(true); echo "<p>Done!</p>"; Director::redirect($_GET['returnURL']); } else { $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); } }
function testManifestIgnoresClassesInStrings() { $baseFolder = TEMP_FOLDER . '/manifest-test'; $manifestInfo = ManifestBuilder::get_manifest_info($baseFolder); /* If a class defintion is listed in a single quote string, then it shouldn't be inlcuded. Here we have put a class definition for MyClass_InSingleQuoteString inside a single-quoted string */ $this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST'])); $this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists'])); $this->assertNotContains('MyClass_InSingleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents'])); /* Ditto for double quotes. Here we have put a class definition for MyClass_InDoubleQuoteString inside a double-quoted string. */ $this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST'])); $this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists'])); $this->assertNotContains('MyClass_InDoubleQuoteString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents'])); /* Finally, we need to ensure that class definitions inside heredoc strings aren't included. Here, we have defined the class MyClass_InHeredocString inside a heredoc string. */ $this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_CLASS_MANIFEST'])); $this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['exists'])); $this->assertNotContains('MyClass_InHeredocString', array_keys($manifestInfo['globals']['_ALL_CLASSES']['parents'])); }
/** * Updates the database schema, creating tables & fields as necessary. */ function build() { // The default time limit of 30 seconds is normally not enough increase_time_limit_to(600); // Get all our classes ManifestBuilder::create_manifest_file(); require MANIFEST_FILE; if (isset($_GET['returnURL'])) { echo "<p>Setting up the database; you will be returned to your site shortly....</p>"; $this->doBuild(true); echo "<p>Done!</p>"; Director::redirect($_GET['returnURL']); } else { if (!Director::is_cli() && Director::urlParam('Controller') == __CLASS__) { echo '<p style="color: red;"><i>db/build</i> has been deprecated. Please use <b>dev/build</b> instead.</p>'; } $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); } }
/** * Updates the database schema, creating tables & fields as necessary. */ function build() { if(Director::isLive() && Security::database_is_ready() && !Director::is_cli() && !Permission::check("ADMIN")) { Security::permissionFailure($this, "This page is secured and you need administrator rights to access it. " . "Enter your credentials below and we will send you right along."); return; } // The default time limit of 30 seconds is normally not enough if(ini_get("safe_mode") != "1") { set_time_limit(600); } // Get all our classes ManifestBuilder::create_manifest_file(); require(MANIFEST_FILE); $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); }
/** * Build a {@link SQLQuery} object to perform the given query. * * @param string $filter A filter to be inserted into the WHERE clause. * @param string|array $sort A sort expression to be inserted into the ORDER BY clause. If omitted, self::$default_sort will be used. * @param string|array $limit A limit expression to be inserted into the LIMIT clause. * @param string $join A single join clause. This can be used for filtering, only 1 instance of each DataObject will be returned. * @param boolean $restictClasses Restrict results to only objects of either this class of a subclass of this class * @param string $having A filter to be inserted into the HAVING clause. * * @return SQLQuery Query built. */ public function buildSQL($filter = "", $sort = "", $limit = "", $join = "", $restrictClasses = true, $having = "") { // Find a default sort if(!$sort) { $sort = $this->stat('default_sort'); } // Get the tables to join to $tableClasses = ClassInfo::dataClassesFor($this->class); if(!$tableClasses) { if(!ManifestBuilder::has_been_included()) { user_error("DataObjects have been requested before the manifest is loaded. Please ensure you are not querying the database in _config.php.", E_USER_ERROR); } else { user_error("DataObject::buildSQL: Can't find data classes (classes linked to tables) for $this->class. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR); } } $baseClass = array_shift($tableClasses); $select = array("`$baseClass`.*"); // Build our intial query $query = new SQLQuery($select); $query->from("`$baseClass`"); $query->where($filter); $query->orderby($sort); $query->limit($limit); // Add SQL for multi-value fields on the base table $databaseFields = $this->databaseFields(); if($databaseFields) foreach($databaseFields as $k => $v) { if(!in_array($k, array('ClassName', 'LastEdited', 'Created'))) { if(ClassInfo::classImplements($v, 'CompositeDBField')) { $this->dbObject($k)->addToQuery($query); } } } // Join all the tables if($tableClasses && self::$subclass_access) { foreach($tableClasses as $tableClass) { $query->from[$tableClass] = "LEFT JOIN `$tableClass` ON `$tableClass`.ID = `$baseClass`.ID"; $query->select[] = "`$tableClass`.*"; // Add SQL for multi-value fields $SNG = singleton($tableClass); $databaseFields = $SNG->databaseFields(); if($databaseFields) foreach($databaseFields as $k => $v) { if(!in_array($k, array('ClassName', 'LastEdited', 'Created'))) { if(ClassInfo::classImplements($v, 'CompositeDBField')) { $SNG->dbObject($k)->addToQuery($query); } } } } } $query->select[] = "`$baseClass`.ID"; $query->select[] = "if(`$baseClass`.ClassName,`$baseClass`.ClassName,'$baseClass') AS RecordClassName"; // Get the ClassName values to filter to $classNames = ClassInfo::subclassesFor($this->class); if(!$classNames) { user_error("DataObject::get() Can't find data sub-classes for '$callerClass'"); } // If querying the base class, don't bother filtering on class name if($restrictClasses && $this->class != $baseClass) { // Get the ClassName values to filter to $classNames = ClassInfo::subclassesFor($this->class); if(!$classNames) { user_error("DataObject::get() Can't find data sub-classes for '$callerClass'"); } $query->where[] = "`$baseClass`.ClassName IN ('" . implode("','", $classNames) . "')"; } if($having) { $query->having[] = $having; } if($join) { $query->from[] = $join; $query->groupby[] = reset($query->from) . ".ID"; } return $query; }
// Find the URL of this script if (isset($_FILE_TO_URL_MAPPING)) { $fullPath = $testPath = $_SERVER['SCRIPT_FILENAME']; while ($testPath && $testPath != "/") { if (isset($_FILE_TO_URL_MAPPING[$testPath])) { $url = $_FILE_TO_URL_MAPPING[$testPath] . substr($fullPath, strlen($testPath)); $_SERVER['HTTP_HOST'] = parse_url($url, PHP_URL_HOST); $_SERVER['SCRIPT_NAME'] = parse_url($url, PHP_URL_PATH); $_SERVER['REQUEST_PORT'] = parse_url($url, PHP_URL_PORT); break; } $testPath = dirname($testPath); } } if (ManifestBuilder::staleManifest()) { ManifestBuilder::compileManifest(); } require_once MANIFEST_FILE; if (isset($_GET['debugmanifest'])) { Debug::show(file_get_contents(MANIFEST_FILE)); } if (!isset(Director::$environment_type)) { Director::set_environment_type($envType); } // Default director Director::addRules(10, array('Security/$Action' => 'Security', 'db/$Action' => 'DatabaseAdmin', '$Controller/$Action/$ID/$OtherID' => '*', 'images/$Action/$Class/$ID/$Field' => 'Image_Uploader', '' => '->home/', '$URLSegment/$Action/$ID/$OtherID' => 'ModelAsController')); // Load error handlers Debug::loadErrorHandlers(); // Connect to database require_once "core/model/DB.php"; DB::connect($databaseConfig);
<?php // Simulate an execution from sapphire/cli-script.php, Core.php has too many // hardcoded assumptions about folder depth of the executing script. // Overrides paths relative to this file (in sapphire/tests/FullTestSuite.php) $_SERVER['SCRIPT_FILENAME'] = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'cli-script.php'; $_SERVER['SCRIPT_NAME'] = '.' . DIRECTORY_SEPARATOR . 'sapphire' . DIRECTORY_SEPARATOR . 'cli-script.php'; define('BASE_PATH', rtrim(dirname(dirname(dirname(__FILE__)))), DIRECTORY_SEPARATOR); // Copied from cli-script.php, to enable same behaviour through phpunit runner. if (isset($_SERVER['argv'][2])) { $args = array_slice($_SERVER['argv'], 2); $_GET = array(); foreach ($args as $arg) { if (strpos($arg, '=') == false) { $_GET['args'][] = $arg; } else { $newItems = array(); parse_str(substr($arg, 0, 2) == '--' ? substr($arg, 2) : $arg, $newItems); $_GET = array_merge($_GET, $newItems); } } $_REQUEST = $_GET; } if (!class_exists('Object')) { require_once "sapphire/core/Core.php"; global $databaseConfig; DB::connect($databaseConfig); } $_SERVER['REQUEST_URI'] = BASE_URL . '/dev'; ManifestBuilder::load_test_manifest();
/** * Updates the database schema, creating tables & fields as necessary. * * @param boolean $quiet Don't show messages * @param boolean $populate Populate the database, as well as setting up its schema */ function doBuild($quiet = false, $populate = true) { $conn = DB::getConn(); if ($quiet) { DB::quiet(); } else { echo "<h2>Building Database</h2>"; } // Set up the initial database if (!DB::isActive()) { if (!$quiet) { echo '<p><b>Creating database</b></p>'; } global $databaseConfig; $parameters = $databaseConfig ? $databaseConfig : $_REQUEST['db']; $connect = DB::getConnect($parameters); $username = $parameters['username']; $password = $parameters['password']; $database = $parameters['database']; DB::createDatabase($connect, $username, $password, $database); // ManifestBuilder::compileManifest(); } // Get all our classes // ManifestBuilder::compileManifest(); // ManifestBuilder::includeEverything(); // Build the database. Most of the hard work is handled by DataObject $dataClasses = ClassInfo::subclassesFor('DataObject'); array_shift($dataClasses); if (!$quiet) { echo '<p><b>Creating database tables</b></p>'; } $conn->beginSchemaUpdate(); foreach ($dataClasses as $dataClass) { // Test_ indicates that it's the data class is part of testing system if (strpos($dataClass, 'Test_') === false) { if (!$quiet) { echo "<li>{$dataClass}</li>"; } singleton($dataClass)->requireTable(); } } $conn->endSchemaUpdate(); ManifestBuilder::update_db_tables(); if ($populate) { if (!$quiet) { echo '<p><b>Creating database records</b></p>'; } foreach ($dataClasses as $dataClass) { // Test_ indicates that it's the data class is part of testing system if (strpos($dataClass, 'Test_') === false) { if (!$quiet) { echo "<li>{$dataClass}</li>"; } singleton($dataClass)->requireDefaultRecords(); } } } touch(TEMP_FOLDER . '/database-last-generated-' . str_replace(array('\\', '/', ':'), '.', Director::baseFolder())); if (isset($_REQUEST['from_installer'])) { echo "OK"; } }
/** * Build a {@link SQLQuery} object to perform the given query. * * @param string $filter A filter to be inserted into the WHERE clause. * @param string|array $sort A sort expression to be inserted into the ORDER BY clause. If omitted, self::$default_sort will be used. * @param string|array $limit A limit expression to be inserted into the LIMIT clause. * @param string $join A single join clause. This can be used for filtering, only 1 instance of each DataObject will be returned. * @param boolean $restictClasses Restrict results to only objects of either this class of a subclass of this class * @param string $having A filter to be inserted into the HAVING clause. * * @return SQLQuery Query built. */ public function buildSQL($filter = "", $sort = "", $limit = "", $join = "", $restrictClasses = true, $having = "") { // Cache the big hairy part of buildSQL if (!isset(self::$cache_buildSQL_query[$this->class])) { // Get the tables to join to $tableClasses = ClassInfo::dataClassesFor($this->class); if (!$tableClasses) { if (!ManifestBuilder::has_been_included()) { user_error("DataObjects have been requested before the manifest is loaded. Please ensure you are not querying the database in _config.php.", E_USER_ERROR); } else { user_error("DataObject::buildSQL: Can't find data classes (classes linked to tables) for {$this->class}. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR); } } $baseClass = array_shift($tableClasses); // $collidingFields will keep a list fields that appear in mulitple places in the class // heirarchy for this table. They will be dealt with more explicitly in the SQL query // to ensure that junk data from other tables doesn't corrupt data objects $collidingFields = array(); // Build our intial query $query = new SQLQuery(array()); $query->from("\"{$baseClass}\""); // Add SQL for multi-value fields on the base table $databaseFields = self::database_fields($baseClass); if ($databaseFields) { foreach ($databaseFields as $k => $v) { if (!in_array($k, array('ClassName', 'LastEdited', 'Created')) && ClassInfo::classImplements($v, 'CompositeDBField')) { $this->dbObject($k)->addToQuery($query); } else { $query->select[$k] = "\"{$baseClass}\".\"{$k}\""; } } } // Join all the tables if ($tableClasses && self::$subclass_access) { foreach ($tableClasses as $tableClass) { $query->from[$tableClass] = "LEFT JOIN \"{$tableClass}\" ON \"{$tableClass}\".\"ID\" = \"{$baseClass}\".\"ID\""; // Add SQL for multi-value fields $databaseFields = self::database_fields($tableClass); $compositeFields = self::composite_fields($tableClass, false); if ($databaseFields) { foreach ($databaseFields as $k => $v) { if (!isset($compositeFields[$k])) { // Update $collidingFields if necessary if (isset($query->select[$k])) { if (!isset($collidingFields[$k])) { $collidingFields[$k] = array($query->select[$k]); } $collidingFields[$k][] = "\"{$tableClass}\".\"{$k}\""; } else { $query->select[$k] = "\"{$tableClass}\".\"{$k}\""; } } } } if ($compositeFields) { foreach ($compositeFields as $k => $v) { $dbO = $this->dbObject($k); if ($dbO) { $dbO->addToQuery($query); } } } } } // Resolve colliding fields if ($collidingFields) { foreach ($collidingFields as $k => $collisions) { $caseClauses = array(); foreach ($collisions as $collision) { if (preg_match('/^"([^"]+)"/', $collision, $matches)) { $collisionBase = $matches[1]; $collisionClasses = ClassInfo::subclassesFor($collisionBase); $caseClauses[] = "WHEN \"{$baseClass}\".\"ClassName\" IN ('" . implode("', '", $collisionClasses) . "') THEN {$collision}"; } else { user_error("Bad collision item '{$collision}'", E_USER_WARNING); } } $query->select[$k] = "CASE " . implode(" ", $caseClauses) . " ELSE NULL END" . " AS \"{$k}\""; } } $query->select[] = "\"{$baseClass}\".\"ID\""; $query->select[] = "CASE WHEN \"{$baseClass}\".\"ClassName\" IS NOT NULL THEN \"{$baseClass}\".\"ClassName\" ELSE '{$baseClass}' END AS \"RecordClassName\""; // Get the ClassName values to filter to $classNames = ClassInfo::subclassesFor($this->class); if (!$classNames) { user_error("DataObject::get() Can't find data sub-classes for '{$callerClass}'"); } // If querying the base class, don't bother filtering on class name if ($restrictClasses && $this->class != $baseClass) { // Get the ClassName values to filter to $classNames = ClassInfo::subclassesFor($this->class); if (!$classNames) { user_error("DataObject::get() Can't find data sub-classes for '{$callerClass}'"); } $query->where[] = "\"{$baseClass}\".\"ClassName\" IN ('" . implode("','", $classNames) . "')"; } self::$cache_buildSQL_query[$this->class] = clone $query; } else { $query = clone self::$cache_buildSQL_query[$this->class]; } // Find a default sort if (!$sort) { $sort = $this->stat('default_sort'); } // Add quoting to sort expression if it's a simple column name if (preg_match('/^[A-Z][A-Z0-9_]*$/i', $sort)) { $sort = "\"{$sort}\""; } $query->where($filter); $query->orderby($sort); $query->limit($limit); if ($having) { $query->having[] = $having; } if ($join) { $query->from[] = $join; // In order to group by unique columns we have to group by everything listed in the select foreach ($query->select as $field) { // Skip the _SortColumns; these are only going to be aggregate functions if (preg_match('/AS\\s+\\"?_SortColumn/', $field, $matches)) { // Identify columns with aliases, and ignore the alias. Making use of the alias in // group by was causing problems when those queries were subsequently passed into // SQLQuery::unlimitedRowCount. } else { if (preg_match('/^(.*)\\s+AS\\s+(\\"[^"]+\\")\\s*$/', $field, $matches)) { $query->groupby[] = $matches[1]; // Otherwise just use the field as is } else { $query->groupby[] = $field; } } } } return $query; }
function coverage() { if(hasPhpUnit()) { ManifestBuilder::load_all_classes(); $tests = ClassInfo::subclassesFor('SapphireTest'); array_shift($tests); unset($tests['FunctionalTest']); $this->runTests($tests, true); } else { echo "Please install PHPUnit using pear"; } }
function testThemeRetrieval() { $ds = DIRECTORY_SEPARATOR; $testThemeBaseDir = TEMP_FOLDER . $ds . 'test-themes'; if (file_exists($testThemeBaseDir)) { Filesystem::removeFolder($testThemeBaseDir); } mkdir($testThemeBaseDir); mkdir($testThemeBaseDir . $ds . 'blackcandy'); mkdir($testThemeBaseDir . $ds . 'blackcandy_blog'); mkdir($testThemeBaseDir . $ds . 'darkshades'); mkdir($testThemeBaseDir . $ds . 'darkshades_blog'); $this->assertEquals(array('blackcandy' => 'blackcandy', 'darkshades' => 'darkshades'), ManifestBuilder::get_themes($testThemeBaseDir), 'Our test theme directory contains 2 themes'); $this->assertEquals(array('blackcandy' => 'blackcandy', 'blackcandy_blog' => 'blackcandy_blog', 'darkshades' => 'darkshades', 'darkshades_blog' => 'darkshades_blog'), ManifestBuilder::get_themes($testThemeBaseDir, true), 'Our test theme directory contains 2 themes and 2 sub-themes'); // Remove all the test themes we created Filesystem::removeFolder($testThemeBaseDir); }
*/ increase_memory_limit_to('64M'); /////////////////////////////////////////////////////////////////////////////// // INCLUDES require_once "core/ManifestBuilder.php"; require_once "core/ClassInfo.php"; require_once 'core/Object.php'; require_once 'core/control/Director.php'; require_once 'filesystem/Filesystem.php'; require_once "core/Session.php"; /////////////////////////////////////////////////////////////////////////////// // MANIFEST /** * Include the manifest */ ManifestBuilder::include_manifest(); /** * ?debugmanifest=1 hook */ if (isset($_GET['debugmanifest'])) { Debug::show(file_get_contents(MANIFEST_FILE)); } // If this is a dev site, enable php error reporting // This is necessary to force developers to acknowledge and fix // notice level errors (you can override this directive in your _config.php) if (Director::isLive()) { if (defined('E_DEPRECATED')) { error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED); } else { error_reporting(E_ALL ^ E_NOTICE); }
/** * Include everything, so that actually *all* classes are available and * build a map of classes and their subclasses * * @param $classManifest An array of all Sapphire classes; keys are class names and values are filenames * * @return array Returns an array that holds all class relevant * information. */ private static function allClasses($classManifest) { self::$classArray = array(); self::$extendsArray = array(); self::$implementsArray = array(); // Include everything, so we actually have *all* classes foreach ($classManifest as $file) { $b = basename($file); if ($b != 'cli-script.php' && $b != 'main.php') { self::parse_file($file); } } $allClasses["parents"] = self::find_parents(); $allClasses["children"] = self::find_children(); $allClasses["implementors"] = self::$implementsArray; foreach (self::$classArray as $class => $info) { $allClasses['exists'][$class] = $class; } // Build a map of classes and their subclasses $_classes = get_declared_classes(); foreach ($_classes as $class) { $allClasses['exists'][$class] = $class; foreach ($_classes as $subclass) { if (is_subclass_of($class, $subclass)) { $allClasses['parents'][$class][$subclass] = $subclass; } if (is_subclass_of($subclass, $class)) { $allClasses['children'][$class][$subclass] = $subclass; } } } return $allClasses; }
/** * Include everything, so that actually *all* classes are available and * build a map of classes and their subclasses * * @param $classManifest An array of all Sapphire classes; keys are class names and values are filenames * * @return array Returns an array that holds all class relevant * information. */ private static function allClasses($classManifest) { self::$classArray = array(); self::$extendsArray = array(); self::$implementsArray = array(); // Include everything, so we actually have *all* classes foreach ($classManifest as $file) { $b = basename($file); if ($b != 'cli-script.php' && $b != 'main.php') { self::parse_file($file); } } $allClasses["parents"] = self::find_parents(); $allClasses["children"] = self::find_children(); $allClasses["implementors"] = self::$implementsArray; foreach (self::$classArray as $class => $info) { $allClasses['exists'][$class] = $class; // Class names are converted to lowercase for lookup to adhere to PHP's case-insensitive // way of dealing with them. $allClasses['file'][strtolower($class)] = $info['file']; } // Build a map of classes and their subclasses $_classes = get_declared_classes(); foreach ($_classes as $class) { $allClasses['exists'][$class] = $class; foreach ($_classes as $subclass) { if (is_subclass_of($class, $subclass)) { $allClasses['parents'][$class][$subclass] = $subclass; } if (is_subclass_of($subclass, $class)) { $allClasses['children'][$class][$subclass] = $subclass; } } } return $allClasses; }
/** * Run tests for one or more "modules". * A module is generally a toplevel folder, e.g. "mysite" or "sapphire". */ function module($request, $coverage = false) { ManifestBuilder::load_test_manifest(); $classNames = array(); $moduleNames = explode(',', $request->param('ModuleName')); foreach ($moduleNames as $moduleName) { $classesForModule = ClassInfo::classes_for_folder($moduleName); if ($classesForModule) { foreach ($classesForModule as $class) { if (class_exists($class) && is_subclass_of($class, 'SapphireTest')) { $classNames[] = $class; } } } } $this->runTests($classNames, $coverage); }
/** * Generates the template manifest - a list of all the .SS files in the * application */ private static function getTemplateManifest($baseDir, $folder, &$templateManifest, &$cssManifest, $themeName = null) { $items = scandir("{$baseDir}/{$folder}"); if ($items) { foreach ($items as $item) { if (substr($item, 0, 1) == '.') { continue; } if (substr($item, -3) == '.ss') { $templateName = substr($item, 0, -3); $templateType = substr($folder, strrpos($folder, '/') + 1); if ($templateType == "templates") { $templateType = "main"; } if ($themeName) { $templateManifest[$templateName]['themes'][$themeName][$templateType] = "{$baseDir}/{$folder}/{$item}"; } else { $templateManifest[$templateName][$templateType] = "{$baseDir}/{$folder}/{$item}"; } } else { if (substr($item, -4) == '.css') { $cssName = substr($item, 0, -4); // Debug::message($item); if ($themeName) { $cssManifest[$cssName]['themes'][$themeName] = "{$folder}/{$item}"; } else { $cssManifest[$cssName]['unthemed'] = "{$folder}/{$item}"; } } else { if (@is_dir("{$baseDir}/{$folder}/{$item}")) { ManifestBuilder::getTemplateManifest($baseDir, "{$folder}/{$item}", $templateManifest, $cssManifest, $themeName); } } } } } }