Ejemplo n.º 1
0
	public function testFindTemplates() {
		$base     = dirname(__FILE__) . '/fixtures/templatemanifest';
		$manifest = new SS_TemplateManifest($base, false, true);
		$loader   = new SS_TemplateLoader();

		$manifest->regenerate(false);
		$loader->pushManifest($manifest);

		$expectPage = array(
			'main'   => "$base/module/templates/Page.ss",
			'Layout' => "$base/module/templates/Layout/Page.ss"
		);
		$expectPageThemed = array(
			'main'   => "$base/themes/theme/templates/Page.ss",
			'Layout' => "$base/themes/theme/templates/Layout/Page.ss"
		);

		$this->assertEquals($expectPage, $loader->findTemplates('Page'));
		$this->assertEquals($expectPage, $loader->findTemplates(array('Foo', 'Page')));
		$this->assertEquals($expectPage, $loader->findTemplates('PAGE'));
		$this->assertEquals($expectPageThemed, $loader->findTemplates('Page', 'theme'));

		$expectPageLayout       = array('main' => "$base/module/templates/Layout/Page.ss");
		$expectPageLayoutThemed = array('main' => "$base/themes/theme/templates/Layout/Page.ss");

		$this->assertEquals($expectPageLayout, $loader->findTemplates('Layout/Page'));
		$this->assertEquals($expectPageLayout, $loader->findTemplates('Layout/PAGE'));
		$this->assertEquals($expectPageLayoutThemed, $loader->findTemplates('Layout/Page', 'theme'));

		$expectCustomPage = array(
			'main'   => "$base/module/templates/Page.ss",
			'Layout' => "$base/module/templates/Layout/CustomPage.ss"
		);
		$this->assertEquals($expectCustomPage, $loader->findTemplates(array('CustomPage', 'Page')));
	}
Ejemplo n.º 2
0
 /**
  * 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'])));
 }
 function beforeCallActionHandler($request, $action)
 {
     if (!$this->owner->response->isFinished() && $action == 'build' && $request->getVar('flush')) {
         SS_TemplateLoader::instance()->getManifest()->regenerate(true);
         SSViewer::flush_template_cache();
     }
 }
 /**
  * Override to check if there is a custom template for this panel, otherwise fall back.
  *
  * @return string
  */
 protected function getTemplate()
 {
     $templateName = get_class($this) . '_' . $this->SubjectPage()->ClassName . '_' . $this->GridFieldName;
     if (SS_TemplateLoader::instance()->findTemplates($templateName)) {
         return $templateName;
     }
     return parent::getTemplate();
 }
 /**
  * Override to check if there is a custom template for this panel, otherwise fall back
  *
  * @return string
  */
 protected function getTemplate()
 {
     $templateName = get_class($this) . '_' . $this->ModelAdminClass . '_' . $this->ModelAdminModel;
     if (SS_TemplateLoader::instance()->findTemplates($templateName)) {
         return $templateName;
     }
     return parent::getTemplate();
 }
Ejemplo n.º 6
0
 public function tearDown()
 {
     SS_TemplateLoader::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();
 }
Ejemplo n.º 7
0
 public function tearDown()
 {
     SS_TemplateLoader::instance()->popManifest();
     i18n::set_locale($this->originalLocale);
     Director::setBaseFolder(null);
     SSViewer::set_theme($this->_oldTheme);
     i18n::register_translator($this->origAdapter, 'core');
     parent::tearDown();
 }
Ejemplo n.º 8
0
 /**
  * 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();
 }
 public function detectTemplate($templates)
 {
     $manifest = SS_TemplateLoader::instance()->getManifest();
     if (Config::inst()->get('SSViewer', 'theme_enabled')) {
         $theme = Config::inst()->get('SSViewer', 'theme');
     } else {
         $theme = null;
     }
     foreach ((array) $templates as $template) {
         if ($manifest->getCandidateTemplate($template, $theme)) {
             return $template;
         }
     }
     return false;
 }
 public function updateCMSFields(FieldList $fields)
 {
     Requirements::css(SEO_DIR . '/css/seo.css');
     // check for Google Sitemaps module & notification;
     $GSMactive = Config::inst()->get('GoogleSitemap', 'enabled', Config::INHERITED);
     $GSMping = Config::inst()->get('GoogleSitemap', 'google_notification_enabled', Config::INHERITED);
     // check for Redirectmanager
     $RedirActive = Object::has_extension("ContentController", "RedirectedURLHandler");
     //$template = new SSViewer('AdminSiteConfigSeoTips');
     //$seotips = $template->process($this->owner->customise(new ArrayData(array(
     $seotips = $this->owner->customise(new ArrayData(array('GSMactive' => $GSMactive, 'GSMping' => $GSMping, 'RedirActive' => $RedirActive)))->renderWith('AdminSiteConfigSeoTips');
     $fields->addFieldToTab("Root.Main", LiteralField::create('SEOtips', $seotips));
     // SEOTITLE
     // parse out the title tag as used by the theme;
     $loader = SS_TemplateLoader::instance();
     $theme = Config::inst()->get('SSViewer', 'theme');
     $foundpath = $loader->findTemplates("main/Page", $theme);
     // TODO: this is a guess...
     $path = $foundpath['main'];
     if (file_exists($path)) {
         $templatecode = file_get_contents($path);
     } else {
         throw new Exception('Failed to identify path');
     }
     if ($templatecode && strpos($templatecode, '<title>')) {
         $templatetag = explode('<title>', $templatecode);
         $templatetag = array_pop($templatetag);
         $templatetag = explode('</title>', $templatetag);
         $templatetag = array_shift($templatetag);
     } else {
         $templatetag = false;
     }
     //		$template = SSViewer::fromString($titlehtml);
     //		$fulltitle = $template->process($this->owner);
     if ($templatetag) {
         $templatetag = "<br />Current template title tag: " . $templatetag;
     } else {
         $templatetag = "";
     }
     // FIXME - not sure of the intention of this value, but set it to avoid site config breaking
     $titlehtml = '';
     $fields->addFieldToTab("Root.Main", $seotitlefield = TextField::create('SEOTitleTemplate')->SetRightTitle("For SEO preview (valid js expression, available vars: page_title, page_menutitle, '.\n\t\t\t\t\t'page_metadata_title), eg:<br /> page_title + ' &raquo; ' +\n\t\t\t\tsiteconfig_title [OR] (page_metadata_title ? page_metadata_title : page_title)" . $titlehtml));
     // set default/initial value
     if (!$this->owner->SEOTitleTemplate) {
         $seotitlefield->setValue("page_title + ' &raquo; ' + siteconfig_title");
     }
 }
Ejemplo n.º 11
0
 public function getStyles()
 {
     $config = SiteConfig::current_site_config();
     if ($config->Theme) {
         Config::inst()->update('SSViewer', 'theme_enabled', true);
         Config::inst()->update('SSViewer', 'theme', $config->Theme);
     }
     $theme = $config->Theme;
     $manifest = SS_TemplateLoader::instance()->getManifest();
     $templates = array();
     // Debug::dump($manifest->getTemplates());
     foreach ($manifest->getTemplates() as $templateName => $templateInfo) {
         $themeexists = $theme && isset($templateInfo['themes'][$theme]) && isset($templateInfo['themes'][$theme]['Styles']);
         if ((isset($templateInfo['Styles']) || $themeexists) && !isset($templates[$templateName])) {
             $templates[$templateName] = array('ID' => trim($templateName), 'Name' => trim(str_replace('_', ' ', $templateName)), 'Layout' => $this->renderWith(array($templateName)));
         }
     }
     return new ArrayList($templates);
 }
 public function __construct($templateList)
 {
     // flush template manifest cache if requested
     if (isset($_GET['flush']) && $_GET['flush'] == 'all') {
         if (Director::isDev() || Director::is_cli() || Permission::check('ADMIN')) {
             self::flush_template_cache();
         } else {
             return Security::permissionFailure(null, 'Please log in as an administrator to flush the template cache.');
         }
     }
     if (!is_array($templateList) && substr((string) $templateList, -3) == '.ss') {
         $this->chosenTemplates['main'] = $templateList;
     } else {
         $this->chosenTemplates = SS_TemplateLoader::instance()->findTemplates($templateList, self::current_theme());
         //Debug::show($this->chosenTemplates);
     }
     if (!$this->chosenTemplates) {
         $templateList = is_array($templateList) ? $templateList : array($templateList);
         user_error("None of these templates can be found in theme '" . self::current_theme() . "': " . implode(".ss, ", $templateList) . ".ss", E_USER_WARNING);
     }
 }
 protected function templateArray()
 {
     global $project;
     $config = SiteConfig::current_site_config();
     if ($config->Theme) {
         Config::inst()->update('SSViewer', 'theme_enabled', true);
         Config::inst()->update('SSViewer', 'theme', $config->Theme);
     }
     $theme = $config->Theme;
     $manifest = SS_TemplateLoader::instance()->getManifest();
     $templateList = array();
     foreach ($manifest->getTemplates() as $template_name => $templateInfo) {
         $projectexists = isset($templateInfo[$project]) && isset($templateInfo[$project]['Patterns']);
         $themeexists = $theme && isset($templateInfo['themes'][$theme]) && isset($templateInfo['themes'][$theme]['Patterns']);
         //always use project template files, and grab template files if not already used
         if ($projectexists || $themeexists && !isset($templateList[$template_name])) {
             $templateList[$template_name] = array('Link' => Controller::join_links(Director::absoluteBaseUrl(), 'patterns', 'index', $template_name), 'Name' => $this->stripeTemplateName($template_name), 'Template' => $template_name);
         }
     }
     ksort($templateList);
     return $templateList;
 }
Ejemplo n.º 14
0
 /**
  * @param string $identifier A template name without '.ss' extension or path
  * @param string $type The template type, either "main", "Includes" or "Layout"
  * @return string Full system path to a template file
  */
 public static function getTemplateFileByType($identifier, $type)
 {
     $loader = SS_TemplateLoader::instance();
     $found = $loader->findTemplates("{$type}/{$identifier}", self::current_theme());
     if ($found) {
         return $found['main'];
     }
 }
Ejemplo n.º 15
0
 /**
  * Tests that {@link ContentController::getViewer()} chooses the correct templates.
  *
  * @covers ContentController::getViewer()
  **/
 public function testGetViewer()
 {
     $self = $this;
     $this->useTestTheme(dirname(__FILE__), 'controllertest', function () use($self) {
         // Test a page without a controller (ContentControllerTest_PageWithoutController.ss)
         $page = new ContentControllerTestPageWithoutController();
         $page->URLSegment = "test";
         $page->write();
         $page->publish("Stage", "Live");
         $response = $self->get($page->RelativeLink());
         $self->assertEquals("ContentControllerTestPageWithoutController", trim($response->getBody()));
         // // This should fall over to user Page.ss
         $page = new ContentControllerTestPage();
         $page->URLSegment = "test";
         $page->write();
         $page->publish("Stage", "Live");
         $response = $self->get($page->RelativeLink());
         $self->assertEquals("Page", trim($response->getBody()));
         // Test that the action template is rendered.
         $page = new ContentControllerTestPage();
         $page->URLSegment = "page-without-controller";
         $page->write();
         $page->publish("Stage", "Live");
         $response = $self->get($page->RelativeLink("test"));
         $self->assertEquals("ContentControllerTestPage_test", trim($response->getBody()));
         // Test that an action without a template will default to the index template, which is
         // to say the default Page.ss template
         $response = $self->get($page->RelativeLink("testwithouttemplate"));
         $self->assertEquals("Page", trim($response->getBody()));
         // Test that an action with a template will render the both action template *and* the
         // correct parent template
         $controller = new ContentController($page);
         $viewer = $controller->getViewer('test');
         $templateList = array('ContentControllerTestPage_test', 'Page');
         $expected = SS_TemplateLoader::instance()->findTemplates($templateList, 'controllertest');
         $self->assertEquals($expected, $viewer->templates());
     });
 }
Ejemplo n.º 16
0
 /**
  * @param string $identifier A template name without '.ss' extension or path
  * @param string $type The template type, either "main", "Includes" or "Layout"
  *
  * @return string Full system path to a template file
  */
 public static function getTemplateFileByType($identifier, $type)
 {
     $loader = SS_TemplateLoader::instance();
     if (Config::inst()->get('SSViewer', 'theme_enabled')) {
         $theme = Config::inst()->get('SSViewer', 'theme');
     } else {
         $theme = null;
     }
     $found = $loader->findTemplates("{$type}/{$identifier}", $theme);
     if (isset($found['main'])) {
         return $found['main'];
     } else {
         if (!empty($found)) {
             $founds = array_values($found);
             return $founds[0];
         }
     }
 }
Ejemplo n.º 17
0
// 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.
$flush = (isset($_GET['flush']) || isset($_REQUEST['url']) && (
	$_REQUEST['url'] == 'dev/build' || $_REQUEST['url'] == BASE_URL . '/dev/build'
));
$manifest = new SS_ClassManifest(BASE_PATH, false, $flush);

$loader = SS_ClassLoader::instance();
$loader->registerAutoloader();
$loader->pushManifest($manifest);

// Now that the class manifest is up, load the configuration
$configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush);
Config::inst()->pushConfigManifest($configManifest);

SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(
	BASE_PATH, false, isset($_GET['flush'])
));

// If in live mode, ensure deprecation, strict and notices are not reported
if(Director::isLive()) {
	error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE));
}

///////////////////////////////////////////////////////////////////////////////
// POST-MANIFEST COMMANDS

/**
 * Load error handlers
 */
Debug::loadErrorHandlers();
 public function run($request)
 {
     echo 'Run with ?clear=1 to clear empty database before running the task<br/>';
     echo 'Run with ?overwrite=1 to overwrite templates that exists in the cms<br/>';
     echo 'Run with ?templates=xxx,yyy to specify which template should be imported<br/>';
     echo 'Run with ?subsite=1 to create email templates in all subsites as well. Overwriting is based on main site.<br/>';
     echo '<hr/>';
     $overwrite = $request->getVar('overwrite');
     $clear = $request->getVar('clear');
     $templatesToImport = $request->getVar('templates');
     $importToSubsite = $request->getVar('subsite');
     $subsites = array();
     if ($importToSubsite) {
         $subsites = Subsite::get()->map();
     }
     if ($templatesToImport) {
         $templatesToImport = explode(',', $templatesToImport);
     }
     if ($clear == 1) {
         echo '<strong>Clear all email templates</strong><br/>';
         $emailTemplates = EmailTemplate::get();
         foreach ($emailTemplates as $emailTemplate) {
             $emailTemplate->delete();
         }
     }
     $o = singleton('EmailTemplate');
     $ignoredModules = self::config()->ignored_modules;
     if (!is_array($ignoredModules)) {
         $ignoredModules = array();
     }
     $locales = null;
     if (class_exists('Fluent') && Fluent::locale_names()) {
         if ($o->hasExtension('FluentExtension')) {
             $locales = array_keys(Fluent::locale_names());
         }
     }
     $defaultLocale = i18n::get_locale();
     $templates = SS_TemplateLoader::instance()->getManifest()->getTemplates();
     foreach ($templates as $t) {
         $isOverwritten = false;
         // Emails in mysite/email are not properly marked as emails
         if (isset($t['mysite']) && isset($t['mysite']['email'])) {
             $t['email'] = $t['mysite']['email'];
         }
         // Should be in the /email folder
         if (!isset($t['email'])) {
             continue;
         }
         $filePath = $t['email'];
         $fileName = basename($filePath, '.ss');
         // Should end with *Email
         if (!preg_match('/Email$/', $fileName)) {
             continue;
         }
         $relativeFilePath = str_replace(Director::baseFolder(), '', $filePath);
         $relativeFilePathParts = explode('/', trim($relativeFilePath, '/'));
         // Group by module
         $module = array_shift($relativeFilePathParts);
         // Ignore some modules
         if (in_array($module, $ignoredModules)) {
             continue;
         }
         array_shift($relativeFilePathParts);
         // remove /templates part
         $templateName = str_replace('.ss', '', implode('/', $relativeFilePathParts));
         $templateTitle = basename($templateName);
         // Create a default code from template name
         $code = strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $fileName));
         $code = preg_replace('/-email$/', '', $code);
         if (!empty($templatesToImport) && !in_array($code, $templatesToImport)) {
             echo "<div style='color:blue'>Template with code '{$code}' was ignored.</div>";
             continue;
         }
         $emailTemplate = EmailTemplate::get()->filter('Code', $code)->first();
         if (!$overwrite && $emailTemplate) {
             echo "<div style='color:blue'>Template with code '{$code}' already exists.</div>";
             continue;
         }
         // Create a default title from code
         $title = explode('-', $code);
         $title = array_map(function ($item) {
             return ucfirst($item);
         }, $title);
         $title = implode(' ', $title);
         // Get content of the email
         $content = file_get_contents($filePath);
         // Analyze content to find incompatibilities
         $errors = array();
         if (strpos($content, '<% with') !== false) {
             $errors[] = 'Replace "with" blocks by plain calls to the variable';
         }
         if (strpos($content, '<% if') !== false) {
             $errors[] = 'If/else logic is not supported. Please create one template by use case or abstract logic into the model';
         }
         if (strpos($content, '<% loop') !== false) {
             $errors[] = 'Loops are not supported. Please create a helper method on the model to render the loop';
         }
         if (strpos($content, '<% sprintf') !== false) {
             $errors[] = 'You should not use sprintf to escape content, please use plain _t calls';
         }
         if (!empty($errors)) {
             echo "<div style='color:red'>Invalid syntax was found in '{$relativeFilePath}'. Please fix these errors before importing the template<ul>";
             foreach ($errors as $error) {
                 echo '<li>' . $error . '</li>';
             }
             echo '</ul></div>';
             continue;
         }
         // Parse language
         $collector = new i18nTextCollector();
         $entities = $collector->collectFromTemplate($content, $fileName, $module);
         $translationTable = array();
         foreach ($entities as $entity => $data) {
             if ($locales) {
                 foreach ($locales as $locale) {
                     i18n::set_locale($locale);
                     if (!isset($translationTable[$entity])) {
                         $translationTable[$entity] = array();
                     }
                     $translationTable[$entity][$locale] = i18n::_t($entity);
                 }
                 i18n::set_locale($defaultLocale);
             } else {
                 $translationTable[$entity] = array($defaultLocale => i18n::_t($entity));
             }
         }
         $contentLocale = array();
         foreach ($locales as $locale) {
             $contentLocale[$locale] = $content;
         }
         foreach ($translationTable as $entity => $translationData) {
             $escapedEntity = str_replace('.', '\\.', $entity);
             $baseTranslation = null;
             foreach ($translationData as $locale => $translation) {
                 if (!$baseTranslation && $translation) {
                     $baseTranslation = $translation;
                 }
                 if (!$translation) {
                     $translation = $baseTranslation;
                 }
                 // This regex should match old and new style
                 $count = 0;
                 $contentLocale[$locale] = preg_replace("/<%(t | _t\\(')" . $escapedEntity . "( |').*?%>/ums", $translation, $contentLocale[$locale], -1, $count);
                 if (!$count) {
                     throw new Exception("Failed to replace {$escapedEntity} with translation {$translation}");
                 }
             }
         }
         if (!$emailTemplate) {
             $emailTemplate = new EmailTemplate();
         } else {
             $isOverwritten = true;
         }
         // Scan for extra models based on convention
         preg_match_all('/\\$([a-zA-Z]+)\\./ms', $contentLocale[$defaultLocale], $matches);
         $extraModels = array();
         if (!empty($matches) && !empty($matches[1])) {
             $arr = array_unique($matches[1]);
             foreach ($arr as $n) {
                 if (strtolower($n) === 'siteconfig') {
                     continue;
                 }
                 if (class_exists($n)) {
                     $extraModels[$n] = $n;
                 }
             }
         }
         // Apply content to email
         $this->assignContent($emailTemplate, $contentLocale[$defaultLocale]);
         if (!empty($locales)) {
             foreach ($locales as $locale) {
                 $this->assignContent($emailTemplate, $contentLocale[$locale], $locale);
             }
         }
         // Title
         $emailTemplate->Title = $title;
         if (!empty($locales)) {
             // By convention, we store the translation under NameOfTheTemplateEmail.SUBJECT
             foreach ($locales as $locale) {
                 i18n::set_locale($locale);
                 $localeField = 'Title_' . $locale;
                 $entity = $templateTitle . '.SUBJECT';
                 $translation = i18n::_t($entity);
                 if (!$translation) {
                     $translation = $title;
                 }
                 $emailTemplate->{$localeField} = $translation;
                 if (strpos($translation, '%s') !== false) {
                     echo '<div style="color:red">There is a %s in the title that should be replaced in locale ' . $locale . '!</div>';
                 }
                 if ($locale == $defaultLocale) {
                     $emailTemplate->Title = $translation;
                 }
             }
             i18n::set_locale($defaultLocale);
         }
         // Other properties
         $emailTemplate->Code = $code;
         $emailTemplate->Category = $module;
         $emailTemplate->setExtraModelsAsArray($extraModels);
         $emailTemplate->write();
         $subsiteImport = '';
         // Loop through subsites
         if ($importToSubsite) {
             $subsiteImport .= ' => Main site and subsites';
             Subsite::$disable_subsite_filter = true;
             foreach ($subsites as $subsiteID => $subsiteTitle) {
                 $subsiteEmailTemplate = EmailTemplate::get()->filter(array('Code' => $code, 'SubsiteID' => $subsiteID))->first();
                 $emailTemplateCopy = $emailTemplate;
                 $emailTemplateCopy->SubsiteID = $subsiteID;
                 if ($subsiteEmailTemplate) {
                     $emailTemplateCopy->ID = $subsiteEmailTemplate->ID;
                 } else {
                     $emailTemplateCopy->ID = 0;
                     // New
                 }
                 $emailTemplateCopy->write();
             }
         }
         if ($isOverwritten) {
             echo "<div style='color:orange'>Overwrote {$emailTemplate->Code}{$subsiteImport}</div>";
         } else {
             echo "<div style='color:green'>Imported {$emailTemplate->Code}{$subsiteImport}</div>";
         }
     }
 }
 /**
  * Test against a theme.
  *
  * @param $themeBaseDir string - themes directory
  * @param $theme string - theme name
  * @param $callback Closure
  */
 protected function useTestTheme($themeBaseDir, $theme, $callback)
 {
     Config::nest();
     global $project;
     $manifest = new SS_TemplateManifest($themeBaseDir, $project, true, true);
     SS_TemplateLoader::instance()->pushManifest($manifest);
     Config::inst()->update('SSViewer', 'theme', $theme);
     $e = null;
     try {
         $callback();
     } catch (Exception $e) {
         /* NOP for now, just save $e */
     }
     // Remove all the test themes we created
     SS_TemplateLoader::instance()->popManifest();
     Config::unnest();
     if ($e) {
         throw $e;
     }
 }
Ejemplo n.º 20
0
require_once 'core/manifest/TemplateManifest.php';
require_once 'core/manifest/TokenisedRegularExpression.php';
///////////////////////////////////////////////////////////////////////////////
// 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.
$flush = isset($_GET['flush']) || isset($_REQUEST['url']) && ($_REQUEST['url'] == 'dev/build' || $_REQUEST['url'] == BASE_URL . '/dev/build');
$manifest = new SS_ClassManifest(BASE_PATH, false, $flush);
$loader = SS_ClassLoader::instance();
$loader->registerAutoloader();
$loader->pushManifest($manifest);
// Now that the class manifest is up, load the configuration
$configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush);
Config::inst()->pushConfigManifest($configManifest);
SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(BASE_PATH, false, isset($_GET['flush'])));
// If in live mode, ensure deprecation, strict and notices are not reported
if (Director::isLive()) {
    error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE));
}
///////////////////////////////////////////////////////////////////////////////
// POST-MANIFEST COMMANDS
/**
 * Load error handlers
 */
Debug::loadErrorHandlers();
// initialise the dependency injector
$default_options = array('locator' => 'SilverStripeServiceConfigurationLocator');
Injector::inst($default_options);
///////////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
 public function run($request)
 {
     echo 'Run with ?clear=1 to clear empty database before running the task<br/>';
     echo 'Run with ?overwrite=soft|hard to overwrite templates that exists in the cms. Soft will replace template if not modified by the user, hard will replace template even if modified by user.<br/>';
     echo 'Run with ?templates=xxx,yyy to specify which template should be imported<br/>';
     echo 'Run with ?subsite=all|subsiteID to create email templates in all subsites (including main site) or only in the chosen subsite (if a subsite is active, it will be used by default).<br/>';
     echo 'Run with ?locales=fr,en to choose which locale to import.<br/>';
     echo '<strong>Remember to flush the templates/translations if needed</strong><br/>';
     echo '<hr/>';
     $overwrite = $request->getVar('overwrite');
     $clear = $request->getVar('clear');
     $templatesToImport = $request->getVar('templates');
     $importToSubsite = $request->getVar('subsite');
     $chosenLocales = $request->getVar('locales');
     // Normalize argument
     if ($overwrite && $overwrite != 'soft' && $overwrite != 'hard') {
         $overwrite = 'soft';
     }
     $subsites = array();
     if ($importToSubsite == 'all') {
         $subsites = Subsite::get()->map();
     } else {
         if (is_numeric($importToSubsite)) {
             $subsites = array($importToSubsite => Subsite::get()->byID($importToSubsite)->Title);
         }
     }
     if (class_exists('Subsite') && Subsite::currentSubsiteID()) {
         DB::alteration_message("Importing to current subsite. Run from main site to import other subsites at once.", "created");
         $subsites = array();
     }
     if (!empty($subsites)) {
         DB::alteration_message("Importing to subsites : " . implode(',', array_values($subsites)), "created");
     }
     if ($templatesToImport) {
         $templatesToImport = explode(',', $templatesToImport);
     }
     if ($clear == 1) {
         DB::alteration_message("Clear all email templates", "created");
         $emailTemplates = EmailTemplate::get();
         foreach ($emailTemplates as $emailTemplate) {
             $emailTemplate->delete();
         }
     }
     $emailTemplateSingl = singleton('EmailTemplate');
     $ignoredModules = self::config()->ignored_modules;
     if (!is_array($ignoredModules)) {
         $ignoredModules = array();
     }
     $locales = null;
     if (class_exists('Fluent') && Fluent::locale_names()) {
         if ($emailTemplateSingl->hasExtension('FluentExtension')) {
             $locales = array_keys(Fluent::locale_names());
             if ($chosenLocales) {
                 $arr = explode(',', $chosenLocales);
                 $locales = array();
                 foreach ($arr as $a) {
                     if (strlen($a) == 2) {
                         $a = i18n::get_locale_from_lang($a);
                     }
                     $locales[] = $a;
                 }
             }
         }
     }
     $defaultLocale = i18n::get_locale();
     $templates = SS_TemplateLoader::instance()->getManifest()->getTemplates();
     foreach ($templates as $t) {
         $isOverwritten = false;
         // Emails in mysite/email are not properly marked as emails
         if (isset($t['mysite']) && isset($t['mysite']['email'])) {
             $t['email'] = $t['mysite']['email'];
         }
         // Should be in the /email folder
         if (!isset($t['email'])) {
             continue;
         }
         $filePath = $t['email'];
         $fileName = basename($filePath, '.ss');
         // Should end with *Email
         if (!preg_match('/Email$/', $fileName)) {
             continue;
         }
         $relativeFilePath = str_replace(Director::baseFolder(), '', $filePath);
         $relativeFilePathParts = explode('/', trim($relativeFilePath, '/'));
         // Group by module
         $module = array_shift($relativeFilePathParts);
         // Ignore some modules
         if (in_array($module, $ignoredModules)) {
             continue;
         }
         array_shift($relativeFilePathParts);
         // remove /templates part
         $templateName = str_replace('.ss', '', implode('/', $relativeFilePathParts));
         $templateTitle = basename($templateName);
         // Create a default code from template name
         $code = strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $fileName));
         $code = preg_replace('/-email$/', '', $code);
         if (!empty($templatesToImport) && !in_array($code, $templatesToImport)) {
             DB::alteration_message("Template with code <b>{$code}</b> was ignored.", "repaired");
             continue;
         }
         $whereCode = array('Code' => $code);
         $emailTemplate = EmailTemplate::get()->filter($whereCode)->first();
         // Check if it has been modified or not
         $templateModified = false;
         if ($emailTemplate) {
             $templateModified = $emailTemplate->Created != $emailTemplate->LastEdited;
         }
         if (!$overwrite && $emailTemplate) {
             DB::alteration_message("Template with code <b>{$code}</b> already exists. Choose overwrite if you want to import again.", "repaired");
             continue;
         }
         if ($overwrite == 'soft' && $templateModified) {
             DB::alteration_message("Template with code <b>{$code}</b> has been modified by the user. Choose overwrite=hard to change.", "repaired");
             continue;
         }
         // Create a default title from code
         $title = explode('-', $code);
         $title = array_map(function ($item) {
             return ucfirst($item);
         }, $title);
         $title = implode(' ', $title);
         // Get content of the email
         $content = file_get_contents($filePath);
         // Analyze content to find incompatibilities
         $errors = array();
         if (strpos($content, '<% with') !== false) {
             $errors[] = 'Replace "with" blocks by plain calls to the variable';
         }
         if (strpos($content, '<% if') !== false) {
             $errors[] = 'If/else logic is not supported. Please create one template by use case or abstract logic into the model';
         }
         if (strpos($content, '<% loop') !== false) {
             $errors[] = 'Loops are not supported. Please create a helper method on the model to render the loop';
         }
         if (strpos($content, '<% sprintf') !== false) {
             $errors[] = 'You should not use sprintf to escape content, please use plain _t calls';
         }
         if (!empty($errors)) {
             echo "<div style='color:red'>Invalid syntax was found in '{$relativeFilePath}'. Please fix these errors before importing the template<ul>";
             foreach ($errors as $error) {
                 echo '<li>' . $error . '</li>';
             }
             echo '</ul></div>';
             continue;
         }
         // Parse language
         $collector = new i18nTextCollector();
         $entities = $collector->collectFromTemplate($content, $fileName, $module);
         $translationTable = array();
         foreach ($entities as $entity => $data) {
             if ($locales) {
                 foreach ($locales as $locale) {
                     i18n::set_locale($locale);
                     if (!isset($translationTable[$entity])) {
                         $translationTable[$entity] = array();
                     }
                     $translationTable[$entity][$locale] = i18n::_t($entity);
                 }
                 i18n::set_locale($defaultLocale);
             } else {
                 $translationTable[$entity] = array($defaultLocale => i18n::_t($entity));
             }
         }
         $contentLocale = array();
         foreach ($locales as $locale) {
             $contentLocale[$locale] = $content;
         }
         foreach ($translationTable as $entity => $translationData) {
             $escapedEntity = str_replace('.', '\\.', $entity);
             $baseTranslation = null;
             foreach ($translationData as $locale => $translation) {
                 if (!$baseTranslation && $translation) {
                     $baseTranslation = $translation;
                 }
                 if (!$translation) {
                     $translation = $baseTranslation;
                 }
                 // This regex should match old and new style
                 $count = 0;
                 $contentLocale[$locale] = preg_replace("/<%(t | _t\\(')" . $escapedEntity . "( |').*?%>/ums", $translation, $contentLocale[$locale], -1, $count);
                 if (!$count) {
                     throw new Exception("Failed to replace {$escapedEntity} with translation {$translation}");
                 }
             }
         }
         if (!$emailTemplate) {
             $emailTemplate = new EmailTemplate();
         } else {
             $isOverwritten = true;
         }
         // Scan for extra models based on convention
         preg_match_all('/\\$([a-zA-Z]+)\\./ms', $contentLocale[$defaultLocale], $matches);
         $extraModels = array();
         if (!empty($matches) && !empty($matches[1])) {
             $arr = array_unique($matches[1]);
             foreach ($arr as $n) {
                 if (strtolower($n) === 'siteconfig') {
                     continue;
                 }
                 if (class_exists($n)) {
                     $extraModels[$n] = $n;
                 }
             }
         }
         // Apply content to email
         $this->assignContent($emailTemplate, $contentLocale[$defaultLocale]);
         if (!empty($locales)) {
             foreach ($locales as $locale) {
                 $this->assignContent($emailTemplate, $contentLocale[$locale], $locale);
             }
         }
         // Title
         $emailTemplate->Title = $title;
         if (!empty($locales)) {
             // By convention, we store the translation under NameOfTheTemplateEmail.SUBJECT
             foreach ($locales as $locale) {
                 i18n::set_locale($locale);
                 $localeField = 'Title_' . $locale;
                 $entity = $templateTitle . '.SUBJECT';
                 $translation = i18n::_t($entity);
                 if (!$translation) {
                     $translation = $title;
                     DB::alteration_message("No title found in {$locale} for {$title}. You should define {$templateTitle}.SUBJECT", "error");
                 }
                 $emailTemplate->{$localeField} = $translation;
                 if (strpos($translation, '%s') !== false) {
                     echo '<div style="color:red">There is a %s in the title that should be replaced in locale ' . $locale . '!</div>';
                 }
                 if ($locale == $defaultLocale) {
                     $emailTemplate->Title = $translation;
                 }
             }
             i18n::set_locale($defaultLocale);
         }
         // Other properties
         $emailTemplate->Code = $code;
         $emailTemplate->Category = $module;
         if (class_exists('Subsite') && Subsite::currentSubsiteID()) {
             $emailTemplate->SubsiteID = Subsite::currentSubsiteID();
         }
         $emailTemplate->setExtraModelsAsArray($extraModels);
         // Write to main site or current subsite
         $emailTemplate->write();
         $this->resetLastEditedDate($emailTemplate->ID);
         // Loop through subsites
         if (!empty($importToSubsite)) {
             Subsite::$disable_subsite_filter = true;
             foreach ($subsites as $subsiteID => $subsiteTitle) {
                 $whereCode['SubsiteID'] = $subsiteID;
                 $subsiteEmailTemplate = EmailTemplate::get()->filter($whereCode)->first();
                 $emailTemplateCopy = $emailTemplate;
                 $emailTemplateCopy->SubsiteID = $subsiteID;
                 if ($subsiteEmailTemplate) {
                     $emailTemplateCopy->ID = $subsiteEmailTemplate->ID;
                 } else {
                     $emailTemplateCopy->ID = 0;
                     // New
                 }
                 $emailTemplateCopy->write();
                 $this->resetLastEditedDate($emailTemplateCopy->ID);
             }
         }
         if ($isOverwritten) {
             DB::alteration_message("Overwrote <b>{$emailTemplate->Code}</b>", "created");
         } else {
             DB::alteration_message("Imported <b>{$emailTemplate->Code}</b>", "created");
         }
     }
 }
Ejemplo n.º 22
0
// 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
if (Director::isLive()) {
    error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE));
}
///////////////////////////////////////////////////////////////////////////////
// POST-MANIFEST COMMANDS
/**
 * Load error handlers
 */
Debug::loadErrorHandlers();
///////////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
/**
 * Creates a class instance by the "singleton" design pattern.
 * It will always return the same instance for this class,
 /**
  * Find an alternative template for the current page in a separate theme
  * 
  * @param type $inTheme 
  */
 protected function findAlternate($inTheme, $templates = array(), $action = null)
 {
     if (is_array($templates)) {
         if (count($templates) == 0) {
             // duplicated from Controller::getViewer
             $parentClass = $this->owner->class;
             if ($action && $action != 'index') {
                 $parentClass = $this->owner->class;
                 while ($parentClass != "Controller" && $parentClass != 'DataObject') {
                     $templates[] = strtok($parentClass, '_') . '_' . $action;
                     $parentClass = get_parent_class($parentClass);
                 }
             }
             // Add controller templates for inheritance chain
             $parentClass = $this->owner->class;
             // This is slightly different from Controller::getViewer to prevent
             // picking up the cms/controller template in the findTemplates call
             while ($parentClass != "ContentController" && $parentClass != 'DataObject') {
                 $templates[] = strtok($parentClass, '_');
                 $parentClass = get_parent_class($parentClass);
             }
         }
         // remove duplicates
         $templates = array_unique($templates);
     }
     $other = SS_TemplateLoader::instance()->findTemplates($templates, $inTheme);
     // check that the theme's path is actually in the returned paths
     foreach ($other as $key => $path) {
         if (strpos($path, 'themes/' . $inTheme) === false) {
             unset($other[$key]);
         }
     }
     if (count($other)) {
         return $other;
     }
 }
Ejemplo n.º 24
0
 /**
  * @return SS_TemplateLoader
  */
 public static function instance()
 {
     return self::$instance ? self::$instance : (self::$instance = new self());
 }
 /**
  * Find the appropriate "$Layout" template for this class
  * @throws Exception
  * @return string
  */
 protected function findLayout()
 {
     $theme = Config::inst()->get('SSViewer', 'theme');
     $templateList = array();
     $parentClass = $this->getOwner()->class;
     while ($parentClass !== 'SiteTree') {
         $templateList[] = $parentClass;
         $parentClass = get_parent_class($parentClass);
     }
     $templates = SS_TemplateLoader::instance()->findTemplates($templateList, $theme);
     if (!isset($templates['Layout'])) {
         throw new Exception('No layout found for class: ' . get_class($this->getOwner()));
     }
     return $templates['Layout'];
 }
 /**
  * @return mixed
  * @throws Exception
  */
 public function getTemplate()
 {
     $templates = SS_TemplateLoader::instance()->findTemplates($tryTemplates = $this->getTemplates(), Config::inst()->get('SSViewer', 'theme'));
     if (!$templates) {
         throw new Exception('Can\'t find a template from list: "' . implode('", "', $tryTemplates) . '"');
     }
     return reset($templates);
 }
 /**
  * Loads all the static .ss templates as HTML into memory
  */
 protected function loadTemplates()
 {
     $manifest = SS_TemplateLoader::instance()->getManifest();
     $templates = $manifest->getTemplates();
     $total = sizeof($templates);
     $count = 0;
     $this->output->clearProgress();
     foreach ($templates as $name => $data) {
         foreach ($manifest->getCandidateTemplate($name, $this->theme) as $template) {
             $this->samples[] = $template;
         }
         $count++;
         $this->output->updateProgressPercent($count, $total);
     }
     $this->output->writeln();
 }
Ejemplo n.º 28
0
 function tearDown()
 {
     SS_TemplateLoader::instance()->popManifest();
     i18n::set_locale($this->originalLocale);
     parent::tearDown();
 }
Ejemplo n.º 29
0
	function tearDown() {
		SS_TemplateLoader::instance()->popManifest();
		parent::tearDown();
	}