function testGetItemPath() { $ds = DIRECTORY_SEPARATOR; $loader = new SS_ClassLoader(); $loader->pushManifest($this->testManifest1); $this->assertEquals( $this->baseManifest1 . $ds . 'module' . $ds . 'classes' . $ds . 'ClassA.php', $loader->getItemPath('ClassA') ); $this->assertEquals( false, $loader->getItemPath('UnknownClass') ); $this->assertEquals( false, $loader->getItemPath('OtherClassA') ); $loader->pushManifest($this->testManifest2); $this->assertEquals( false, $loader->getItemPath('ClassA') ); $this->assertEquals( false, $loader->getItemPath('UnknownClass') ); $this->assertEquals( $this->baseManifest2 . $ds . 'module' . $ds . 'classes' . $ds . 'OtherClassA.php', $loader->getItemPath('OtherClassA') ); }
public function testGetItemPath() { $loader = new SS_ClassLoader(); $loader->pushManifest($this->testManifest1); $this->assertEquals(realpath($this->baseManifest1 . '/module/classes/ClassA.php'), realpath($loader->getItemPath('ClassA'))); $this->assertEquals(false, $loader->getItemPath('UnknownClass')); $this->assertEquals(false, $loader->getItemPath('OtherClassA')); $loader->pushManifest($this->testManifest2); $this->assertEquals(false, $loader->getItemPath('ClassA')); $this->assertEquals(false, $loader->getItemPath('UnknownClass')); $this->assertEquals(realpath($this->baseManifest2 . '/module/classes/OtherClassA.php'), realpath($loader->getItemPath('OtherClassA'))); }
function executeInSubprocess($includeStderr = false) { // Get the path to the ErrorControlChain class $classpath = SS_ClassLoader::instance()->getItemPath('ErrorControlChain'); $suppression = $this->suppression ? 'true' : 'false'; // Start building a PHP file that will execute the chain $src = '<' . "?php\nrequire_once '{$classpath}';\n\n\$chain = new ErrorControlChain();\n\n\$chain->setSuppression({$suppression});\n\n\$chain\n"; // For each step, use reflection to pull out the call, stick in the the PHP source we're building foreach ($this->steps as $step) { $func = new ReflectionFunction($step['callback']); $source = file($func->getFileName()); $start_line = $func->getStartLine() - 1; $end_line = $func->getEndLine(); $length = $end_line - $start_line; $src .= implode("", array_slice($source, $start_line, $length)) . "\n"; } // Finally add a line to execute the chain $src .= "->execute();"; // Now stick it in a temporary file & run it $codepath = TEMP_FOLDER . '/ErrorControlChainTest_' . sha1($src) . '.php'; if ($includeStderr) { $null = '&1'; } else { $null = is_writeable('/dev/null') ? '/dev/null' : 'NUL'; } file_put_contents($codepath, $src); exec("php {$codepath} 2>{$null}", $stdout, $errcode); unlink($codepath); return array(implode("\n", $stdout), $errcode); }
/** * Pushes a class and template manifest instance that include tests onto the * top of the loader stacks. */ public static function use_test_manifest() { $classManifest = new SS_ClassManifest(BASE_PATH, true, isset($_GET['flush'])); SS_ClassLoader::instance()->pushManifest($classManifest); SapphireTest::set_test_class_manifest($classManifest); SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(BASE_PATH, true, isset($_GET['flush']))); }
public function __construct($allowed_types = array()) { $this->addComponent(new GridFieldAddNewMultiClass()); $this->addComponent(new GridFieldToolbarHeader()); $this->addComponent(new GridFieldTitleHeader()); $this->addComponent(new GridFieldEditableColumns()); $this->addComponent(new GridFieldEditButton()); $this->addComponent(new GridFieldDeleteAction(false)); $this->addComponent(new GridFieldDetailForm()); // Multi-Class Add Button ///////////////////////// $classes = array(); if (empty($allowed_types)) { $allowed_types = SS_ClassLoader::instance()->getManifest()->getDescendantsOf('FlexiFormHandler'); } foreach ($allowed_types as $className) { $class = singleton($className); $classes[$className] = "{$class->Label()}"; } $component = $this->getComponentByType('GridFieldAddNewMultiClass'); $component->setClasses($classes); // Inline Editing // /////////////// $component = $this->getComponentByType('GridFieldDataColumns'); $component->setDisplayFields(array('Selected' => array('title' => 'Selected', 'callback' => function ($record, $column_name, $grid) { return new CheckboxField_Readonly($column_name); }), 'HandlerName' => array('title' => 'Name', 'field' => 'ReadonlyField'), 'Label' => array('title' => 'Type', 'field' => 'ReadonlyField'), 'DescriptionPreview' => array('title' => 'Description', 'field' => 'ReadonlyField'), 'FormCount' => array('title' => 'Form Count', 'field' => 'ReadonlyField'))); }
/** * Set up the simplest initial query */ public function initialiseQuery() { //@todo could probably use ClassInfo::hasTable() instead here // Get the tables to join to. // Don't get any subclass tables - let lazy loading do that. $tableClasses = ClassInfo::ancestry($this->dataClass, true); // Error checking if (!$tableClasses) { if (!SS_ClassLoader::instance()->hasManifest()) { 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("DataList::create Can't find data classes (classes linked to tables) for" . " {$this->dataClass}. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR); } } //Base table is not an ancestor in OrientDB $baseClass = array_pop($tableClasses); // Build our intial query $this->query = new OrientSQLQuery(array()); $this->query->setDistinct(false); if ($sort = singleton($this->dataClass)->stat('default_sort')) { $this->sort($sort); } //TODO: sometimes we want to set from to be the @RID $this->query->setFrom("{$baseClass}"); $obj = Injector::inst()->get($baseClass); $obj->extend('augmentDataQueryCreation', $this->query, $this); }
public function fire() { $this->info('Used cache location: ' . TEMP_FOLDER); SS_ClassLoader::instance()->getManifest()->regenerate(); $this->info('regenerated manifest!'); ClassInfo::reset_db_cache(); $this->info('resetted db cache!'); }
/** * Get a list of all page types available in the CMS * * @return array */ protected function getPageTypes() { $types = array(); foreach (SS_ClassLoader::instance()->getManifest()->getDescendantsOf("SiteTree") as $class) { $types[$class] = $class; } return $types; }
/** * The callback that Phockito will call every time there's a new double created * * @param string $double - The class name of the new double * @param string $of - The class new of the doubled class or interface * @param bool $isDoubleOfInterface - True if $of is an interface, False if it's a class */ static function register_double($double, $of, $isDoubleOfInterface = false) { $manifest = SS_ClassLoader::instance()->getManifest(); if (!$manifest instanceof PhockitoClassManifestUpdater) { $manifest = new PhockitoClassManifestUpdater($manifest); SS_ClassLoader::instance()->pushManifest($manifest, true); } $manifest->addDouble($double, $of, $isDoubleOfInterface); }
public function tearDown() { SS_TemplateLoader::instance()->popManifest(); SS_ClassLoader::instance()->popManifest(); i18n::set_locale($this->originalLocale); Config::inst()->update('Director', 'alternate_base_folder', null); Config::inst()->update('SSViewer', 'theme', $this->_oldTheme); i18n::register_translator($this->origAdapter, 'core'); parent::tearDown(); }
public function tearDown() { SS_TemplateLoader::instance()->popManifest(); SS_ClassLoader::instance()->popManifest(); i18n::set_locale($this->originalLocale); Director::setBaseFolder(null); SSViewer::set_theme($this->_oldTheme); i18n::register_translator($this->origAdapter, 'core'); parent::tearDown(); }
/** * Pushes a class and template manifest instance that include tests onto the * top of the loader stacks. */ public static function use_test_manifest() { $classManifest = new SS_ClassManifest(BASE_PATH, true, isset($_GET['flush'])); SS_ClassLoader::instance()->pushManifest($classManifest, false); SapphireTest::set_test_class_manifest($classManifest); SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(BASE_PATH, project(), true, isset($_GET['flush']))); Config::inst()->pushConfigStaticManifest(new SS_ConfigStaticManifest(BASE_PATH, true, isset($_GET['flush']))); // Invalidate classname spec since the test manifest will now pull out new subclasses for each internal class // (e.g. Member will now have various subclasses of DataObjects that implement TestOnly) DataObject::clear_classname_spec_cache(); }
/** * @param $controller * * @return bool|string */ protected function findControllerFilePath($controller) { $controller = strtolower($controller); $classes = SS_ClassLoader::instance()->getManifest()->getClasses(); $filePath = isset($classes[$controller]) ? $classes[$controller] : ''; if (!is_file($filePath)) { $this->error("{$filePath} does not exist"); return false; } return $filePath; }
/** * Inits bundle directory structure * * @param InputInterface $input * @param OutputInterface $output */ protected function initBundleDirectoryStructure(InputInterface $input, OutputInterface $output) { // Bootstrap SS so we can use module listing $frameworkPath = $this->container->getParameter('behat.silverstripe_extension.framework_path'); $_GET['flush'] = 1; require_once $frameworkPath . '/core/Core.php'; unset($_GET['flush']); $featuresPath = $input->getArgument('features'); if (!$featuresPath) { throw new \InvalidArgumentException('Please specify a module name (e.g. "@mymodule")'); } // Can't use 'behat.paths.base' since that's locked at this point to base folder (not module) $pathSuffix = $this->container->getParameter('behat.silverstripe_extension.context.path_suffix'); $currentModuleName = null; $modules = \SS_ClassLoader::instance()->getManifest()->getModules(); $currentModuleName = $this->container->getParameter('behat.silverstripe_extension.module'); // get module from short notation if path starts from @ if (preg_match('/^\\@([^\\/\\\\]+)(.*)$/', $featuresPath, $matches)) { $currentModuleName = $matches[1]; // TODO Replace with proper module loader once AJShort's changes are merged into core if (!array_key_exists($currentModuleName, $modules)) { throw new \InvalidArgumentException(sprintf('Module "%s" not found', $currentModuleName)); } $currentModulePath = $modules[$currentModuleName]; } if (!$currentModuleName) { throw new \InvalidArgumentException('Can not find module to initialize suite.'); } // TODO Retrieve from module definition once that's implemented if ($input->getOption('namespace')) { $namespace = $input->getOption('namespace'); } else { $namespace = ucfirst($currentModuleName); } $namespace .= '\\' . $this->container->getParameter('behat.silverstripe_extension.context.namespace_suffix'); $featuresPath = rtrim($currentModulePath . DIRECTORY_SEPARATOR . $pathSuffix, DIRECTORY_SEPARATOR); $basePath = $this->container->getParameter('behat.paths.base') . DIRECTORY_SEPARATOR; $bootstrapPath = $featuresPath . DIRECTORY_SEPARATOR . 'bootstrap'; $contextPath = $bootstrapPath . DIRECTORY_SEPARATOR . 'Context'; if (!is_dir($featuresPath)) { mkdir($featuresPath, 0777, true); mkdir($bootstrapPath, 0777, true); // touch($bootstrapPath.DIRECTORY_SEPARATOR.'_manifest_exclude'); $output->writeln('<info>+d</info> ' . str_replace($basePath, '', realpath($featuresPath)) . ' <comment>- place your *.feature files here</comment>'); } if (!is_dir($contextPath)) { mkdir($contextPath, 0777, true); $className = $this->container->getParameter('behat.context.class'); file_put_contents($contextPath . DIRECTORY_SEPARATOR . $className . '.php', strtr($this->getFeatureContextSkelet(), array('%NAMESPACE%' => $namespace))); $output->writeln('<info>+f</info> ' . str_replace($basePath, '', realpath($contextPath)) . DIRECTORY_SEPARATOR . 'FeatureContext.php <comment>- place your feature related code here</comment>'); } }
/** * Updates the database schema, creating tables & fields as necessary. */ public function build() { // The default time limit of 30 seconds is normally not enough increase_time_limit_to(600); // Get all our classes SS_ClassLoader::instance()->getManifest()->regenerate(); 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>"; $this->redirect($_GET['returnURL']); } else { $this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate'])); } }
/** * 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 SS_ClassLoader::instance()->getManifest()->regenerate(); 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'])); } }
/** * Gets the fields to configure the panel settings * * @return FieldList */ public function getConfiguration() { $fields = parent::getConfiguration(); $modeladmins = array(); $models = $this->getManagedModelsFor($this->ModelAdminClass); foreach (SS_ClassLoader::instance()->getManifest()->getDescendantsOf("ModelAdmin") as $class) { $SNG = Injector::inst()->get($class); if ($SNG instanceof TestOnly) { continue; } $title = Config::inst()->get($class, "menu_title", Config::INHERITED); $modeladmins[$class] = $title ? $title : $class; } $fields->push(TextField::create("Count", _t('DashbordModelAdmin.COUNT', 'Number of records to display'))); $fields->push(DropdownField::create("ModelAdminClass", _t('Dashboard.MODELADMINCLASS', 'Model admin tab'), $modeladmins)->addExtraClass('no-chzn')->setAttribute('data-lookupurl', $this->Link("modelsforpanel"))->setEmptyString("--- " . _t('Dashboard.PLEASESELECT', 'Please select') . " ---")); $fields->push(DropdownField::create("ModelAdminModel", _t('Dashboard.MODELADMINMODEL', 'Model'), $models)->addExtraClass('no-chzn')); return $fields; }
/** * Updates the database schema, creating tables & fields as necessary. */ public function build() { // The default time limit of 30 seconds is normally not enough increase_time_limit_to(600); // Get all our classes SS_ClassLoader::instance()->getManifest()->regenerate(); $url = $this->getReturnURL(); if ($url) { echo "<p>Setting up the database; you will be returned to your site shortly....</p>"; $this->doBuild(true); echo "<p>Done!</p>"; $this->redirect($url); } else { $quiet = $this->request->requestVar('quiet') !== null; $fromInstaller = $this->request->requestVar('from_installer') !== null; $populate = $this->request->requestVar('dont_populate') === null; $this->doBuild($quiet || $fromInstaller, $populate); } }
/** * @return array */ public static function get_searchable_classes() { // First get any explicitly declared searchable classes $searchable = Config::inst()->get('ShopSearch', 'searchable'); if (is_string($searchable) && strlen($searchable) > 0) { $searchable = array($searchable); } elseif (!is_array($searchable)) { $searchable = array(); } // Add in buyables automatically if asked if (Config::inst()->get('ShopSearch', 'buyables_are_searchable')) { $buyables = SS_ClassLoader::instance()->getManifest()->getImplementorsOf('Buyable'); if (is_array($buyables) && count($buyables) > 0) { foreach ($buyables as $c) { $searchable[] = $c; } } } return array_unique($searchable); }
/** * Processes data from container and console input. * * @param InputInterface $input * @param OutputInterface $output * * @throws \RuntimeException */ public function process(InputInterface $input, OutputInterface $output) { $featuresPath = $input->getArgument('features'); // Can't use 'behat.paths.base' since that's locked at this point to base folder (not module) $pathSuffix = $this->container->getParameter('behat.silverstripe_extension.context.path_suffix'); $currentModuleName = null; $modules = \SS_ClassLoader::instance()->getManifest()->getModules(); // get module specified in behat.yml $currentModuleName = $this->container->getParameter('behat.silverstripe_extension.module'); // get module from short notation if path starts from @ if ($featuresPath && preg_match('/^\\@([^\\/\\\\]+)(.*)$/', $featuresPath, $matches)) { $currentModuleName = $matches[1]; // TODO Replace with proper module loader once AJShort's changes are merged into core $currentModulePath = $modules[$currentModuleName]; $featuresPath = str_replace('@' . $currentModuleName, $currentModulePath . DIRECTORY_SEPARATOR . $pathSuffix, $featuresPath); // get module from provided features path } elseif (!$currentModuleName && $featuresPath) { $path = realpath(preg_replace('/\\.feature\\:.*$/', '.feature', $featuresPath)); foreach ($modules as $moduleName => $modulePath) { if (false !== strpos($path, realpath($modulePath))) { $currentModuleName = $moduleName; $currentModulePath = realpath($modulePath); break; } } $featuresPath = $currentModulePath . DIRECTORY_SEPARATOR . $pathSuffix . DIRECTORY_SEPARATOR . $featuresPath; // if module is configured for profile and feature provided } elseif ($currentModuleName && $featuresPath) { $currentModulePath = $modules[$currentModuleName]; $featuresPath = $currentModulePath . DIRECTORY_SEPARATOR . $pathSuffix . DIRECTORY_SEPARATOR . $featuresPath; } if ($input->getOption('namespace')) { $namespace = $input->getOption('namespace'); } else { $namespace = ucfirst($currentModuleName); } if ($currentModuleName) { $this->container->get('behat.silverstripe_extension.context.class_guesser')->setNamespaceBase($namespace); } $this->container->get('behat.console.command')->setFeaturesPaths($featuresPath ? array($featuresPath) : array()); }
/** * Set up the simplest intial query */ function initialiseQuery() { // Get the tables to join to $tableClasses = ClassInfo::dataClassesFor($this->dataClass); // Error checking if (!$tableClasses) { if (!SS_ClassLoader::instance()->hasManifest()) { 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->dataClass}. 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 $this->query = new SQLQuery(array()); $this->query->distinct = true; if ($sort = singleton($this->dataClass)->stat('default_sort')) { $this->sort($sort); } $this->query->from("\"{$baseClass}\""); $this->selectAllFromTable($this->query, $baseClass); singleton($this->dataClass)->extend('augmentDataQueryCreation', $this->query, $this); }
/** * Returns all classes contained in a certain folder. * * @todo Doesn't return additional classes that only begin * with the filename, and have additional naming separated through underscores. * * @param string $folderPath Relative or absolute folder path * @return array Array of class names */ public static function classes_for_folder($folderPath) { $absFolderPath = Director::getAbsFile($folderPath); $matchedClasses = array(); $manifest = SS_ClassLoader::instance()->getManifest()->getClasses(); foreach ($manifest as $class => $compareFilePath) { if (stripos($compareFilePath, $absFolderPath) === 0) { $matchedClasses[] = $class; } } return $matchedClasses; }
function getModule() { $classes = SS_ClassLoader::instance()->getManifest()->getClasses(); $className = strtolower($this->className); if (($pos = strpos($className, '_')) !== false) { $className = substr($className, 0, $pos); } if (isset($classes[$className])) { if (preg_match('/^' . str_replace('/', '\\/', preg_quote(BASE_PATH)) . '\\/([^\\/]+)\\//', $classes[$className], $matches)) { return $matches[1]; } } }
/** * Set up the simplest initial query */ public function initialiseQuery() { // Get the tables to join to. // Don't get any subclass tables - let lazy loading do that. $tableClasses = ClassInfo::ancestry($this->dataClass, true); // Error checking if (!$tableClasses) { if (!SS_ClassLoader::instance()->hasManifest()) { 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->dataClass}. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR); } } $baseClass = array_shift($tableClasses); // Build our intial query $this->query = new SQLQuery(array()); $this->query->setDistinct(true); if ($sort = singleton($this->dataClass)->stat('default_sort')) { $this->sort($sort); } $this->query->setFrom("\"{$baseClass}\""); $obj = Injector::inst()->get($baseClass); $obj->extend('augmentDataQueryCreation', $this->query, $this); }
/** * Pushes a class and template manifest instance that include tests onto the * top of the loader stacks. */ public static function use_test_manifest() { $flush = true; if (isset($_GET['flush']) && $_GET['flush'] === '0') { $flush = false; } $classManifest = new SS_ClassManifest(BASE_PATH, true, $flush); SS_ClassLoader::instance()->pushManifest($classManifest, false); SapphireTest::set_test_class_manifest($classManifest); ThemeResourceLoader::instance()->addSet('$default', new ThemeManifest(BASE_PATH, project(), true, $flush)); Config::inst()->pushConfigStaticManifest(new SS_ConfigStaticManifest(BASE_PATH, true, $flush)); // Invalidate classname spec since the test manifest will now pull out new subclasses for each internal class // (e.g. Member will now have various subclasses of DataObjects that implement TestOnly) DataObject::reset(); }
/** * @deprecated 3.0 Please use {@link SS_ClassManifest::getItemPath()}. */ function getClassFile($className) { Deprecation::notice('3.0', 'Use SS_ClassManifest::getItemPath() instead.'); return SS_ClassLoader::instance()->getManifest()->getItemPath($className); }
/** * @return SS_ClassLoader */ public static function instance() { return self::$instance ? self::$instance : (self::$instance = new self()); }
/** * Includes all available language files for a certain defined locale. * * @param string $locale All resources from any module in locale $locale will be loaded * @param Boolean $clean Clean old caches? */ public static function include_by_locale($locale, $clean = false) { if ($clean) { $cache = Zend_Translate::getCache(); if ($cache) { $cache->clean(Zend_Cache::CLEANING_MODE_ALL); } } // Sort modules by inclusion priority, then alphabetically // TODO Should be handled by priority flags within modules $prios = array('sapphire' => 10, 'framework' => 10, 'admin' => 11, 'cms' => 12, 'mysite' => 90); $modules = SS_ClassLoader::instance()->getManifest()->getModules(); ksort($modules); uksort($modules, function ($a, $b) use(&$prios) { $prioA = isset($prios[$a]) ? $prios[$a] : 50; $prioB = isset($prios[$b]) ? $prios[$b] : 50; return $prioA > $prioB; }); // Loop in reverse order, meaning the translator with the highest priority goes first $translators = array_reverse(self::get_translators(), true); foreach ($translators as $priority => $translators) { foreach ($translators as $name => $translator) { $adapter = $translator->getAdapter(); // Load translations from modules foreach ($modules as $module) { $filename = $adapter->getFilenameForLocale($locale); $filepath = "{$module}/lang/" . $filename; if ($filename && !file_exists($filepath)) { continue; } $adapter->addTranslation(array('content' => $filepath, 'locale' => $locale)); } // Load translations from themes // TODO Replace with theme listing once implemented in TemplateManifest $themesBase = Director::baseFolder() . '/themes'; if (is_dir($themesBase)) { foreach (scandir($themesBase) as $theme) { if (strpos($theme, SSViewer::current_theme()) === 0 && file_exists("{$themesBase}/{$theme}/lang/")) { $filename = $adapter->getFilenameForLocale($locale); $filepath = "{$themesBase}/{$theme}/lang/" . $filename; if ($filename && !file_exists($filepath)) { continue; } $adapter->addTranslation(array('content' => $filepath, 'locale' => $locale)); } } } // Add empty translations to ensure the locales are "registered" with isAvailable(), // and the next invocation of include_by_locale() doesn't cause a new reparse. $adapter->addTranslation(array('content' => array($locale => $locale), 'locale' => $locale, 'usetranslateadapter' => true)); } } }
/** * Includes all available language files for a certain defined locale. * * @param string $locale All resources from any module in locale $locale will be loaded * @param Boolean $clean Clean old caches? */ public static function include_by_locale($locale, $clean = false) { if ($clean) { self::flush(); } // Get list of module => path pairs, and then just the names $modules = SS_ClassLoader::instance()->getManifest()->getModules(); $moduleNames = array_keys($modules); // Remove the "project" module from the list - we'll add it back specially later if needed global $project; if (($idx = array_search($project, $moduleNames)) !== false) { array_splice($moduleNames, $idx, 1); } // Get the order from the config syste, $order = Config::inst()->get('i18n', 'module_priority'); // Find all modules that don't have their order specified by the config system $unspecified = array_diff($moduleNames, $order); // If the placeholder "other_modules" exists in the order array, replace it by the unspecified modules if (($idx = array_search('other_modules', $order)) !== false) { array_splice($order, $idx, 1, $unspecified); } else { array_splice($order, 0, 0, $unspecified); } // Put the project module back in at the begining if it wasn't specified by the config system if (!in_array($project, $order)) { array_unshift($order, $project); } $sortedModules = array(); foreach ($order as $module) { if (isset($modules[$module])) { $sortedModules[$module] = $modules[$module]; } } $sortedModules = array_reverse($sortedModules, true); // Loop in reverse order, meaning the translator with the highest priority goes first $translators = array_reverse(self::get_translators(), true); foreach ($translators as $priority => $translators) { foreach ($translators as $name => $translator) { $adapter = $translator->getAdapter(); // Load translations from modules foreach ($sortedModules as $module) { $filename = $adapter->getFilenameForLocale($locale); $filepath = "{$module}/lang/" . $filename; if ($filename && !file_exists($filepath)) { continue; } $adapter->addTranslation(array('content' => $filepath, 'locale' => $locale)); } // Load translations from themes // TODO Replace with theme listing once implemented in TemplateManifest $themesBase = Director::baseFolder() . '/themes'; if (is_dir($themesBase)) { foreach (scandir($themesBase) as $theme) { if (strpos($theme, Config::inst()->get('SSViewer', 'theme')) === 0 && file_exists("{$themesBase}/{$theme}/lang/")) { $filename = $adapter->getFilenameForLocale($locale); $filepath = "{$themesBase}/{$theme}/lang/" . $filename; if ($filename && !file_exists($filepath)) { continue; } $adapter->addTranslation(array('content' => $filepath, 'locale' => $locale)); } } } // Add empty translations to ensure the locales are "registered" with isAvailable(), // and the next invocation of include_by_locale() doesn't cause a new reparse. $adapter->addTranslation(array('content' => array($locale => $locale), 'locale' => $locale, 'usetranslateadapter' => true)); } } }
require_once 'control/injector/Injector.php'; // Initialise the dependency injector as soon as possible, as it is // subsequently used by some of the following code $injector = new Injector(array('locator' => 'SilverStripeServiceConfigurationLocator')); Injector::set_inst($injector); /////////////////////////////////////////////////////////////////////////////// // MANIFEST // Regenerate the manifest if ?flush is set, or if the database is being built. // The coupling is a hack, but it removes an annoying bug where new classes // referenced in _config.php files can be referenced during the build process. $requestURL = isset($_REQUEST['url']) ? trim($_REQUEST['url'], '/') : false; $flush = isset($_GET['flush']) || $requestURL === trim(BASE_URL . '/dev/build', '/'); global $manifest; $manifest = new SS_ClassManifest(BASE_PATH, false, $flush); // Register SilverStripe's class map autoload $loader = SS_ClassLoader::instance(); $loader->registerAutoloader(); $loader->pushManifest($manifest); // Fall back to Composer's autoloader (e.g. for PHPUnit), if composer is used if (file_exists(BASE_PATH . '/vendor/autoload.php')) { require_once BASE_PATH . '/vendor/autoload.php'; } // Now that the class manifest is up, load the static configuration $configManifest = new SS_ConfigStaticManifest(BASE_PATH, false, $flush); Config::inst()->pushConfigStaticManifest($configManifest); // And then the yaml configuration $configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush); Config::inst()->pushConfigYamlManifest($configManifest); // Load template manifest SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(BASE_PATH, project(), false, $flush)); // If in live mode, ensure deprecation, strict and notices are not reported