/** * Avoid subsites filtering on fixture fetching. */ function objFromFixture($class, $id) { Subsite::disable_subsite_filter(true); $obj = parent::objFromFixture($class, $id); Subsite::disable_subsite_filter(false); return $obj; }
public function run($request) { $groups = Group::get(); echo 'Pass ?drop=1 to drop groups without members<br/>'; echo 'Want more dropping? Pass ?permission=1 to also drop groups without permissions even if they have members<br/>'; echo 'Pass ?merge=1 to merge groups with the same code<br/>'; echo 'Want to merge across subsites ? Pass ?subsite=1 to disable subsite filters<br/>'; echo '<hr/>'; $merge = $request->getVar('merge'); $drop = $request->getVar('drop'); $dropNoPermission = $request->getVar('permission'); $subsite = $request->getVar('subsite'); if (class_exists('Subsite') && $subsite) { Subsite::$disable_subsite_filter = true; } if ($drop) { DB::alteration_message("Dropping groups with no members"); if ($dropNoPermission) { DB::alteration_message("Also dropping groups with no permissions"); } foreach ($groups as $group) { if (!$group->Members()->count()) { DB::alteration_message("Removing group {$group->ID} because it has no members", "deleted"); $group->delete(); } if ($dropNoPermission) { $c = $group->Permissions()->count(); if (!$c) { DB::alteration_message("Removing group {$group->ID} because it has no permissions", "deleted"); $group->delete(); } } } } if ($merge) { DB::alteration_message("Merging groups with duplicated codes"); $index = array(); /* @var $group Group */ foreach ($groups as $group) { DB::alteration_message("Found group " . $group->Code); if (!isset($index[$group->Code])) { $index[$group->Code] = $group; DB::alteration_message("First instance of group, do not merge"); continue; } $mergeGroup = $index[$group->Code]; DB::alteration_message('Merge group ' . $group->ID . ' with ' . $mergeGroup->ID, 'repaired'); $i = 0; foreach ($group->Members() as $m) { $i++; $mergeGroup->Members()->add($m); } DB::alteration_message('Added ' . $i . ' members to group', 'created'); DB::alteration_message("Group " . $group->ID . ' was deleted', 'deleted'); $group->delete(); } } DB::alteration_message('All done!'); }
/** * To process this job, we need to get the next page whose ID is the next greater than the last * processed. This way we don't need to remember a bunch of data about what we've processed */ public function process() { if (ClassInfo::exists('Subsite')) { Subsite::disable_subsite_filter(); } $class = $this->reindexType; $pages = $class::get(); $pages = $pages->filter(array('ID:GreaterThan' => $this->lastIndexedID)); $pages = $pages->limit(Config::inst()->get(__CLASS__, 'at_a_time')); $pages = $pages->sort('ID ASC'); if (ClassInfo::exists('Subsite')) { Subsite::$disable_subsite_filter = false; } if (!$pages || !$pages->count()) { $this->isComplete = true; return; } $mode = Versioned::get_reading_mode(); Versioned::reading_stage('Stage'); // index away $service = singleton('SolrSearchService'); $live = array(); $stage = array(); $all = array(); foreach ($pages as $page) { // Make sure the current page is not orphaned. if ($page->ParentID > 0) { $parent = $page->getParent(); if (is_null($parent) || $parent === false) { continue; } } // Appropriately index the current page, taking versioning into account. if ($page->hasExtension('Versioned')) { $stage[] = $page; $base = $page->baseTable(); $idField = '"' . $base . '_Live"."ID"'; $livePage = Versioned::get_one_by_stage($page->ClassName, 'Live', $idField . ' = ' . $page->ID); if ($livePage) { $live[] = $livePage; } } else { $all[] = $page; } $this->lastIndexedID = $page->ID; } if (count($all)) { $service->indexMultiple($all); } if (count($stage)) { $service->indexMultiple($stage, 'Stage'); } if (count($live)) { $service->indexMultiple($live, 'Live'); } Versioned::set_reading_mode($mode); $this->lastIndexedID = $page->ID; $this->currentStep += $pages->count(); }
function getQuery() { $oldState = Subsite::$disable_subsite_filter; Subsite::$disable_subsite_filter = true; $return = parent::getQuery(); Subsite::$disable_subsite_filter = $oldState; return $return; }
/** * @param array $compatibility */ public static function done(array $compatibility) { if (class_exists("Subsite")) { Subsite::$disable_subsite_filter = $compatibility[self::SUBSITES]; } if (class_exists("Translatable")) { Translatable::enable_locale_filter($compatibility[self::TRANSLATABLE]); } }
protected function getItem() { if (ClassInfo::exists('Subsite')) { Subsite::disable_subsite_filter(true); } $item = DataObject::get_by_id($this->itemType, $this->itemID); if (ClassInfo::exists('Subsite')) { Subsite::disable_subsite_filter(false); } return $item; }
function Items() { if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $items = parent::Items(); if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = false; } return $items; }
/** * * @return DataList */ protected function getAllLivePages($subsiteID = 0) { ini_set('memory_limit', '200M'); $oldMode = Versioned::get_reading_mode(); if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); } Versioned::reading_stage('Live'); $pages = DataObject::get("SiteTree"); Versioned::set_reading_mode($oldMode); if (class_exists('Subsite')) { return $pages->filter(array('SubsiteID' => $subsiteID)); } return $pages; }
function testVirtualPageFromAnotherSubsite() { Subsite::$write_hostmap = false; $subsite = $this->objFromFixture('Subsite_Template', 'subsite2'); Subsite::changeSubsite($subsite->ID); Subsite::$disable_subsite_filter = false; $linky = $this->objFromFixture('SiteTree', 'linky'); $svp = new SubsitesVirtualPage(); $svp->CopyContentFromID = $linky->ID; $svp->SubsiteID = $subsite->ID; $svp->URLSegment = 'linky'; $svp->write(); $this->assertEquals($svp->SubsiteID, $subsite->ID); $this->assertEquals($svp->Title, $linky->Title); }
/** * Rewrite links to the $old file to now point to the $new file. * * @uses SiteTree->rewriteFileURL() * * @param String $old File path relative to the webroot * @param String $new File path relative to the webroot */ function updateLinks($old, $new) { if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); } $pages = $this->owner->BackLinkTracking(); $summary = ""; if ($pages) { foreach ($pages as $page) { $page->rewriteFileURL($old, $new); } } if (class_exists('Subsite')) { Subsite::disable_subsite_filter(false); } }
public function loadFixtures() { if (ClassInfo::exists('Subsite')) { $currentSubsite = Subsite::currentSubsiteID(); } foreach (self::$preload_fixtures as $desc) { $fixtureFile = $desc['file']; if (file_exists(Director::baseFolder() . '/' . $fixtureFile)) { $siteID = null; if (isset($desc['subsite'])) { $site = DataObject::get_one('Subsite', '"Title" = \'' . Convert::raw2sql($desc['subsite']) . '\''); if ($site && $site->ID) { $siteID = $site->ID; } if (!$siteID) { // no site, so just skip this file load continue; } } // need to disable the filter when running dev/build so that it actually searches // within the relevant subsite, not the 'current' one. if (ClassInfo::exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $filter = $desc['filter'] . ($siteID ? ' AND "SubsiteID"=' . $siteID : ''); $existing = DataObject::get_one($desc['type'], $filter); if (ClassInfo::exists('Subsite')) { Subsite::$disable_subsite_filter = false; } if (!$existing) { if ($siteID) { Subsite::changeSubsite($siteID); } $fixture = new YamlFixture($fixtureFile); $fixture->saveIntoDatabase(); DB::alteration_message('YAML bootstrap loaded from ' . $fixtureFile, 'created'); } } } if (ClassInfo::exists('Subsite')) { Subsite::changeSubsite($currentSubsite); } }
public function run($request) { set_time_limit(0); increase_memory_limit_to(); Subsite::$disable_subsite_filter = true; $mainConfig = SiteConfig::current_site_config(); $mainConfig->compileStyles(); DB::alteration_message("Compile styles for main site"); $subsites = Subsite::get(); foreach ($subsites as $subsite) { $subsiteConfig = SiteConfig::get()->filter('SubsiteID', $subsite->ID)->first(); if (!$subsiteConfig) { DB::alteration_message("No config for subsite " . $subsite->ID, "error"); continue; } $subsiteConfig->compileStyles(); DB::alteration_message("Compile styles for subsite " . $subsite->ID); } DB::alteration_message("All done"); }
public function init() { if (!Controller::has_curr()) { return; } /* @var $ctrl Controller */ $ctrl = Controller::curr(); /* @ var $req SS_HTTPRequest */ $req = $ctrl->getRequest(); // Otherwise it will get excluded if it does not have access to all subsites... if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $base = AdminRootController::config()->url_base; $defaultPanel = AdminRootController::config()->default_panel; $currentSegment = $req->getURL(); // We will fail if we are redirected to a panel without the proper permission if (($currentSegment == $base || $currentSegment == $base . '/pages') && $defaultPanel == 'CMSPagesController' && !Permission::check('CMS_ACCESS_CMSMain')) { // Instead, let's redirect to something we can access if (Permission::check('CMS_ACCESS')) { $member = Member::currentUser(); $permissions = Permission::permissions_for_member($member->ID); foreach ($permissions as $permission) { if (strpos($permission, 'CMS_ACCESS_') === 0) { $class = str_replace('CMS_ACCESS_', '', $permission); $segment = Config::inst()->get($class, 'url_segment'); $url = Director::absoluteBaseURL() . $base . '/' . $segment; header('Location:' . $url); exit; } } } } if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = false; } }
/** * Builds a comma separated list of human-readbale permissions for a given Member. * * @return string */ public function getPermissionsDescription() { if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); } $permissionsUsr = Permission::permissions_for_member($this->owner->ID); $permissionsSrc = Permission::get_codes(true); sort($permissionsUsr); $permissionNames = array(); foreach ($permissionsUsr as $code) { $code = strtoupper($code); foreach ($permissionsSrc as $k => $v) { if (isset($v[$code])) { $name = empty($v[$code]['name']) ? _t('MemberReportExtension.UNKNOWN', 'Unknown') : $v[$code]['name']; $permissionNames[] = $name; } } } $result = $permissionNames ? implode(', ', $permissionNames) : _t('MemberReportExtension.NOPERMISSIONS', 'No Permissions'); if (class_exists('Subsite')) { Subsite::disable_subsite_filter(false); } return $result; }
public function augmentSyncLinkTracking() { // Set LinkTracking appropriately $links = HTTP::getLinksIn($this->owner->Content); $linkedPages = array(); if ($links) { foreach ($links as $link) { if (substr($link, 0, strlen('http://')) == 'http://') { $withoutHttp = substr($link, strlen('http://')); if (strpos($withoutHttp, '/') && strpos($withoutHttp, '/') < strlen($withoutHttp)) { $domain = substr($withoutHttp, 0, strpos($withoutHttp, '/')); $rest = substr($withoutHttp, strpos($withoutHttp, '/') + 1); $subsiteID = Subsite::getSubsiteIDForDomain($domain); if ($subsiteID == 0) { continue; } // We have no idea what the domain for the main site is, so cant track links to it $origDisableSubsiteFilter = Subsite::$disable_subsite_filter; Subsite::disable_subsite_filter(true); $candidatePage = DataObject::get_one("SiteTree", "\"URLSegment\" = '" . Convert::raw2sql(urldecode($rest)) . "' AND \"SubsiteID\" = " . $subsiteID, false); Subsite::disable_subsite_filter($origDisableSubsiteFilter); if ($candidatePage) { $linkedPages[] = $candidatePage->ID; } else { $this->owner->HasBrokenLink = true; } } } } } $this->owner->CrossSubsiteLinkTracking()->setByIDList($linkedPages); }
/** * Returns the pages that depend on this page. * This includes virtual pages, pages that link to it, etc. * * @param $includeVirtuals Set to false to exlcude virtual pages. */ function DependentPages($includeVirtuals = true) { if (is_callable('Subsite::disable_subsite_filter')) { Subsite::disable_subsite_filter(true); } // Content links $items = $this->BackLinkTracking(); if (!$items) { $items = new DataObjectSet(); } else { foreach ($items as $item) { $item->DependentLinkType = 'Content link'; } } // Virtual pages if ($includeVirtuals) { $virtuals = $this->VirtualPages(); if ($virtuals) { foreach ($virtuals as $item) { $item->DependentLinkType = 'Virtual page'; } $items->merge($virtuals); } } // Redirector pages $redirectors = DataObject::get("RedirectorPage", "\"RedirectorPage\".\"RedirectionType\" = 'Internal' AND \"LinkToID\" = {$this->ID}"); if ($redirectors) { foreach ($redirectors as $item) { $item->DependentLinkType = 'Redirector page'; } $items->merge($redirectors); } if (is_callable('Subsite::disable_subsite_filter')) { Subsite::disable_subsite_filter(false); } return $items; }
/** * * @return DataList */ protected function getAllLivePages() { ini_set('memory_limit', '512M'); $oldMode = Versioned::get_reading_mode(); if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); } if (class_exists('Translatable')) { Translatable::disable_locale_filter(); } Versioned::reading_stage('Live'); $pages = DataObject::get("SiteTree"); Versioned::set_reading_mode($oldMode); return $pages; }
/** * Return a siteconfig for this subsite * * @return \SiteConfig */ public function getSiteConfig() { if (!$this->owner->ID) { return; } if (isset(self::$_current_siteconfig_cache[$this->owner->ID])) { return self::$_current_siteconfig_cache[$this->owner->ID]; } Subsite::$disable_subsite_filter = true; $sc = SiteConfig::get()->filter('SubsiteID', $this->owner->ID)->first(); Subsite::$disable_subsite_filter = false; if (!$sc) { $sc = new SiteConfig(); $sc->SubsiteID = $this->owner->ID; $sc->Title = _t('Subsite.SiteConfigTitle', 'Your Site Name'); $sc->Tagline = _t('Subsite.SiteConfigSubtitle', 'Your tagline here'); $sc->write(); } self::$_current_siteconfig_cache[$this->owner->ID] = $sc; return $sc; }
/** * Get the pop-up fields for the given record. */ function getCustomFieldsFor($childData) { if(!$childData) { user_error("AssetTableField::DetailForm No record found"); return null; } if($childData->ParentID) { $folder = DataObject::get_by_id('File', $childData->ParentID ); } else { $folder = singleton('Folder'); } $urlLink = "<div class='field readonly'>"; $urlLink .= "<label class='left'>"._t('AssetTableField.URL','URL')."</label>"; $urlLink .= "<span class='readonly'><a href='{$childData->Link()}'>{$childData->RelativeLink()}</a></span>"; $urlLink .= "</div>"; $detailFormFields = new FieldSet( new TabSet("BottomRoot", $mainTab = new Tab('Main', new TextField("Title", _t('AssetTableField.TITLE','Title')), new TextField("Name", _t('AssetTableField.FILENAME','Filename')), new LiteralField("AbsoluteURL", $urlLink), new ReadonlyField("FileType", _t('AssetTableField.TYPE','Type')), new ReadonlyField("Size", _t('AssetTableField.SIZE','Size'), $childData->getSize()), new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()), new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded')), new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed')) ) ) ); $mainTab->setTitle(_t('AssetTableField.MAIN', 'Main')); if(is_a($childData, 'Image')) { $tab = $detailFormFields->findOrMakeTab("BottomRoot.Image", _t('AssetTableField.IMAGE', 'Image')); $big = $childData->URL; $formattedImage = $childData->getFormattedImage('AssetLibraryPreview'); $thumbnail = $formattedImage ? $formattedImage->URL : ''; // Hmm this required the translated string to be appended to BottomRoot to add this to the Main tab $detailFormFields->addFieldToTab('BottomRoot.Main', new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions')) ); $tab->push( new LiteralField("ImageFull", "<img id='thumbnailImage' src='{$thumbnail}?r=" . rand(1,100000) . "' alt='{$childData->Name}' />" ) ); } if($childData && $childData->hasMethod('BackLinkTracking')) { if(class_exists('Subsite')) Subsite::disable_subsite_filter(true); $links = $childData->BackLinkTracking(); if(class_exists('Subsite')) Subsite::disable_subsite_filter(false); if($links && $links->exists()) { $backlinks = array(); foreach($links as $link) { $backlinks[] = "<li><a href=\"admin/show/$link->ID\">" . $link->Breadcrumbs(null,true). "</a></li>"; } $backlinks = "<div style=\"clear:left\">". _t('AssetTableField.PAGESLINKING','The following pages link to this file:') ."<ul>" . implode("",$backlinks) . "</ul></div>"; } if(!isset($backlinks)) $backlinks = "<p>". _t('AssetTableField.NOLINKS',"This file hasn't been linked to from any pages.") ."</p>"; $detailFormFields->addFieldToTab("BottomRoot.Links", new LiteralField("Backlinks", $backlinks)); } // the ID field confuses the Controller-logic in finding the right view for ReferencedField $detailFormFields->removeByName('ID'); if($childData) $childData->extend('updateCMSFields', $detailFormFields); return $detailFormFields; }
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"); } } }
public static function merge($records) { $all = array(); $all_but_oldest = array(); $all_but_latest = array(); $latest = null; $oldest = null; foreach ($records as $r) { if (!is_object($r)) { $r = (object) $r; } if (!$r instanceof Member) { $r = Member::get()->byID($r->ID); } if (!$latest) { $latest = $r; } else { if (strtotime($r->LastEdited) > strtotime($latest->LastEdited)) { $latest = $r; } } if (!$oldest) { $oldest = $r; } else { if ($r->ID < $oldest->ID) { $oldest = $r->ID; } } $all[] = $r; } foreach ($all as $a) { if ($a->ID == $oldest->ID) { continue; } $all_but_oldest[] = $a; } foreach ($all as $a) { if ($a->ID == $latest->ID) { continue; } $all_but_latest[] = $a; } if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } Config::inst()->update('DataObject', 'validation_enabled', false); // Rewrite all relations so everything is pointing to oldest // For some reason, the code in merge fails to do this properly $tables = DB::tableList(); $objects = ClassInfo::subclassesFor('DataObject'); foreach ($objects as $o) { $config = $o::config(); if ($config->has_one) { foreach ($config->has_one as $name => $class) { if ($class == 'Member') { $table = ClassInfo::table_for_object_field($o, $name . 'ID'); if ($table && in_array(strtolower($table), $tables)) { foreach ($all_but_oldest as $a) { $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID; DB::alteration_message($sql); DB::query($sql); } } } } } if ($config->has_many) { foreach ($config->has_many as $name => $class) { if ($class == 'Member') { $table = ClassInfo::table_for_object_field($o, $name . 'ID'); if ($table && in_array(strtolower($table), $tables)) { foreach ($all_but_oldest as $a) { $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID; DB::alteration_message($sql); DB::query($sql); } } } } } if ($config->many_many) { foreach ($config->many_many as $name => $class) { if ($class == 'Member') { $table = ClassInfo::table_for_object_field($o, $name . 'ID'); if ($table && in_array(strtolower($table), $tables)) { foreach ($all_but_oldest as $a) { $sql = "UPDATE {$table} SET " . $name . 'ID = ' . $oldest->ID . ' WHERE ' . $name . 'ID = ' . $a->ID; DB::alteration_message($sql); DB::query($sql); } } } } } } // Now, we update to oldest record with the latest info $orgOldest = $oldest; $oldest->merge($latest, 'right', false); foreach ($all_but_oldest as $a) { $a->delete(); } try { $oldest->write(); } catch (Exception $ex) { $orgOldest->write(); } }
/** * Disable the sub-site filtering; queries will select from all subsites */ static function disable_subsite_filter($disabled = true) { self::$disable_subsite_filter = $disabled; }
/** * Get an email template by code * * @param string $code * @return EmailTemplate */ public static function getByCode($code) { $template = EmailTemplate::get()->filter('Code', $code)->first(); // If subsite, fallback to main site email if not defined if (!$template && class_exists('Subsite') && Subsite::currentSubsiteID()) { Subsite::$disable_subsite_filter = true; $template = EmailTemplate::get()->filter('Code', $code)->first(); Subsite::$disable_subsite_filter = false; } // In dev mode, create a placeholder email if (!$template) { $template = new EmailTemplate(); $template->Title = $code; $template->Code = $code; $template->Content = ''; $template->write(); } return $template; }
public function onBeforeInit() { // Theme is not yet defined properly at this time /* @var $request SS_HttpRequest */ $request = $this->owner->getRequest(); $url = $request->getURL(); if (strpos($url, 'dev/build') === 0) { return; } if ($this->isAdminBackend()) { $member = Member::currentUser(); // Silverstripe does not redirect if invalid login to the /admin section so layout will be broken if ($member && $member->ID) { if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $access = Permission::checkMember($member, 'CMS_ACCESS'); if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = false; } if (!$access) { $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : Director::baseURL(); Session::set("Security.Message.message", _t('Security.ALREADYLOGGEDIN')); Session::set("Security.Message.type", 'warning'); Session::set("BackURL", $uri); Session::save(); header('Location:' . Director::absoluteBaseURL() . '/Security/login' . "?BackURL=" . urlencode($uri)); exit; } } return; } $conf = $this->config(); if ($iframe = $request->getVar('iframe')) { if (!$iframe || $iframe == 'disabled') { Cookie::force_expiry('iframe'); } else { Cookie::set('iframe', true); } } $outdated = $conf->outdated_browser; if ($outdated && $outdated['enabled']) { if (Director::isDev()) { ThemeHeadRequirements::javascript(THEME_FRAMEWORK_PATH . '/javascript/outdatedbrowser/outdatedbrowser.js'); Requirements::css(THEME_FRAMEWORK_PATH . '/javascript/outdatedbrowser/outdatedbrowser.css'); } else { ThemeHeadRequirements::javascript(THEME_FRAMEWORK_PATH . '/javascript/outdatedbrowser/outdatedbrowser.min.js'); Requirements::css(THEME_FRAMEWORK_PATH . '/javascript/outdatedbrowser/outdatedbrowser.min.css'); } ThemeHeadRequirements::javascriptTemplate(THEME_FRAMEWORK_PATH . '/javascript/outdated.js', array('BgColor' => $outdated['bg_color'], 'Color' => $outdated['color'], 'LowerThan' => $outdated['lower_than'], 'Lang' => i18n::get_lang_from_locale(i18n::get_locale()))); } if ($conf->include_jquery) { FormExtraJquery::include_jquery(); } if ($conf->include_jquery_ui) { FormExtraJquery::include_jquery_ui(); } $uikit = $conf->uikit; if ($uikit && $uikit['enabled']) { $uikitTheme = 'uikit'; if ($uikit['theme']) { $uikitTheme .= '.' . $uikit['theme']; } $uikitComponents = $uikit['components']; if (Director::isDev()) { Requirements::javascript(THEME_FRAMEWORK_PATH . '/uikit/js/uikit.js'); if ($uikit['theme_enabled']) { Requirements::css(THEME_FRAMEWORK_PATH . '/uikit/css/' . $uikitTheme . '.css'); } foreach ($uikitComponents as $component) { Requirements::javascript(THEME_FRAMEWORK_PATH . '/uikit/js/components/' . $component . '.js'); if ($uikit['theme_enabled']) { $componentTheme = ''; if ($uikit['theme']) { $componentTheme = '.' . $uikit['theme']; } Requirements::css(THEME_FRAMEWORK_PATH . '/uikit/css/components/' . $component . $componentTheme . '.css'); } } } else { Requirements::javascript(THEME_FRAMEWORK_PATH . '/uikit/js/uikit.min.js'); if ($uikit['theme_enabled']) { Requirements::css(THEME_FRAMEWORK_PATH . '/uikit/css/' . $uikitTheme . '.min.css'); } foreach ($uikitComponents as $component) { Requirements::javascript(THEME_FRAMEWORK_PATH . '/uikit/js/components/' . $component . '.min.js'); if ($uikit['theme_enabled']) { $componentTheme = ''; if ($uikit['theme']) { $componentTheme = '.' . $uikit['theme']; } Requirements::css(THEME_FRAMEWORK_PATH . '/uikit/css/components/' . $component . $componentTheme . '.min.css'); } } } // If we loaded notify if (in_array('notify', $uikitComponents)) { if ($this->owner->hasMethod('SessionMessage') && $this->owner->SessionMessage(false)) { $this->sessionMessage = $message = $this->owner->SessionMessage(); $content = Convert::raw2js($message->Content); $type = Convert::raw2js($message->Type); // Convert default Silverstripe types switch ($type) { case self::MESSAGE_BAD: $type = self::NOTIFY_DANGER; break; case self::MESSAGE_GOOD: $type = self::NOTIFY_SUCCESS; break; case self::MESSAGE_WARNING: $type = self::NOTIFY_WARNING; break; case self::MESSAGE_INFO: $type = self::NOTIFY_INFO; break; } Requirements::customScript(<<<JS UIkit.notify('{$content}',{ status: '{$type}', timeout: 0 }); JS ); } } } $noty = $conf->noty; if ($noty && $noty['enabled']) { if (Director::isDev()) { Requirements::javascript(THEME_FRAMEWORK_PATH . '/javascript/noty/packaged/jquery.noty.packaged.js'); } else { Requirements::javascript(THEME_FRAMEWORK_PATH . '/javascript/noty/packaged/jquery.noty.packaged.min.js'); } $theme = $noty['theme']; $layout = $noty['layout']; Requirements::css(THEME_FRAMEWORK_PATH . '/javascript/noty/themes/' . $theme . '.css'); Requirements::customScript(<<<JS jQuery.extend(jQuery.noty.defaults,{ theme: '{$theme}', layout: '{$layout}', closeWith: ['click','button'] }); JS ); // Flash messages if ($this->owner->hasMethod('SessionMessage') && $this->owner->SessionMessage(false)) { $this->sessionMessage = $message = $this->owner->SessionMessage(); $content = Convert::raw2js($message->Content); $type = Convert::raw2js($message->Type); // Convert default Silverstripe types switch ($type) { case self::MESSAGE_BAD: $type = self::NOTY_ERROR; break; case self::MESSAGE_GOOD: $type = self::NOTY_SUCCESS; break; case self::MESSAGE_WARNING: $type = self::NOTY_ALERT; break; case self::MESSAGE_INFO: $type = self::NOTY_INFO; break; } Requirements::customScript(<<<JS noty({ text: '{$content}', type: '{$type}', timeout: false }); JS ); } } // Forcing js to bottom allow to put some scripts tags in the head if we want to Requirements::set_force_js_to_bottom(true); }
/** * * Physically runs the task which - dependent on QueuedJobs being installed and * not skipped via script params - will queue-up chunks of pages to be cached, * or just attempt to cache call objects at once. * * @param SS_HTTPRequest $request * @return void */ public function run($request) { // Increase memory to max-allowable CacheableConfig::configure_memory_limit(); $startTime = time(); $skipQueue = $request->getVar('SkipQueue'); $currentStage = Versioned::current_stage(); /* * Restrict cache rebuild to the given stage - useful for debugging or * "Poor Man's" chunking. */ if ($paramStage = $request->getVar('Stage')) { $stage_mode_mapping = array(ucfirst($paramStage) => strtolower($paramStage)); // All stages } else { $stage_mode_mapping = array("Stage" => "stage", "Live" => "live"); } $canQueue = interface_exists('QueuedJob'); $siteConfigs = DataObject::get('SiteConfig'); foreach ($stage_mode_mapping as $stage => $mode) { Versioned::set_reading_mode('Stage.' . $stage); if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); Config::inst()->update("CacheableSiteConfig", 'cacheable_fields', array('SubsiteID')); Config::inst()->update("CacheableSiteTree", 'cacheable_fields', array('SubsiteID')); } foreach ($siteConfigs as $config) { $service = new CacheableNavigationService($mode, $config); if ($service->refreshCachedConfig()) { echo 'Caching: SiteConfig object ' . trim($config->ID) . ' (' . $config->Title . ') with mode: ' . $mode . self::new_line(2); } else { echo 'Caching fails: SiteConfig object ' . trim($config->ID) . ' (' . $config->Title . ') with mode: ' . $mode . self::new_line(2); } if (class_exists('Subsite')) { $pages = DataObject::get("Page", "SubsiteID = '" . $config->SubsiteID . "'"); } else { $pages = DataObject::get("Page"); } $pageCount = $pages->count(); /* * * Queueing should only occur if: * - QueuedJob module is available * - SkipQueue param is not set * - Total no. pages is greater than the chunk divisor */ $lowPageCount = self::$chunk_divisor > $pageCount; $doQueue = $canQueue && !$skipQueue && !$lowPageCount; if ($pageCount) { $i = 0; $chunkNum = 0; $chunk = array(); foreach ($pages as $page) { $i++; // If QueuedJobs exists and isn't user-disabled: Chunk if ($doQueue) { // Start building a chunk of pages to be refreshed $chunk[] = $page; $chunkSize = count($chunk); /* * Conditions of chunking: * - Initial chunks are chunk-size == self::$chunk_divisor * - Remaining object count equals no. objects in current $chunk */ $doChunking = $this->chunkForQueue($pageCount, $chunkSize, $i); if ($doChunking) { $chunkNum++; $this->queue($service, $chunk, $stage, $config->SubsiteID); echo "Queued chunk #" . $chunkNum . ' (' . $chunkSize . ' objects).' . self::new_line(); $chunk = array(); } // Default to non-chunking if no queuedjobs or script instructed to skip queuing } else { $percentComplete = $this->percentageComplete($i, $pageCount); $service->set_model($page); if ($service->refreshCachedPage(true)) { echo 'Caching: ' . trim($page->Title) . ' (' . $percentComplete . ') ' . self::new_line(); } else { echo 'Caching fails: ' . trim($page->Title) . ' (' . $percentComplete . ') ' . self::new_line(); } } $page->flushCache(); } } $service->completeBuild(); // Completion message $msg = self::new_line() . $pageCount . ' ' . $stage . ' pages in subsite ' . $config->ID; if ($doQueue) { $msg .= ' queued for caching.' . self::new_line(); } else { $msg .= ' objects cached.' . self::new_line(); } echo $msg . self::new_line(); } if (class_exists('Subsite')) { Subsite::disable_subsite_filter(false); } } Versioned::set_reading_mode($currentStage); $endTime = time(); $totalTime = $endTime - $startTime; $this->showConfig($totalTime, $request, $lowPageCount); }
/** * Run the task, and do the business * * @param SS_HTTPRequest $httpRequest */ function run($httpRequest) { require_once 'Zend/Log/Writer/Stream.php'; SS_Log::add_writer(new Zend_Log_Writer_Stream('php://output'), SS_Log::NOTICE); $db = DB::getConn(); if (method_exists($db, 'supportsLocks') && $db->supportsLocks() && !$db->getLock('ScheduledPublishing')) { $this->log('Publication has already been triggered by a different process'); return; } Cookie::$report_errors = false; if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } if (class_exists('Subsite')) { Subsite::$disable_subsite_filter = true; } $this->log('Looking for changes that need to be published'); $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`"; $wfRequests = DataObject::get('WorkflowRequest', "{$bt}Status{$bt} = 'Scheduled' AND {$bt}EmbargoDate{$bt} <= '" . SS_Datetime::now()->getValue() . "'"); $this->log(sprintf('Found %d pages', $wfRequests ? count($wfRequests) : 0)); $admin = Security::findAnAdministrator(); $admin->logIn(); if (count($wfRequests)) { foreach ($wfRequests as $request) { // Use a try block to prevent one bad request // taking down the whole queue try { $page = $request->Page(); $this->log(sprintf("Attempting to publish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); // We remove the embargo date and republish to trigger this. $request->EmbargoDate = null; $result = $request->publish('Page was embargoed. Automatically published.', WorkflowSystemMember::get(), false); $this->log(sprintf("Published '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); } catch (Exception $e) { // Log it? $this->log(sprintf("Failed to publish '%s (URL: %s)", $page->Title, $page->AbsoluteLink())); user_error("Error publishing change to Page ID " . $request->PageID . " - " . $request->Page()->Title . " Error: " . $e->getMessage(), E_USER_WARNING); continue; } } } $this->log('Looking for live pages that need to be expired'); $pagesToExpire = Versioned::get_by_stage('SiteTree', 'Live', "\"ExpiryDate\" <= '" . SS_Datetime::now()->getValue() . "'"); $this->log(sprintf('Found %d pages', $pagesToExpire ? count($pagesToExpire) : 0)); if (count($pagesToExpire)) { foreach ($pagesToExpire as $page) { // Use a try block to prevent one bad request // taking down the whole queue try { $this->log(sprintf("Attempting to unpublish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); // Close any existing workflows if ($wf = $page->openWorkflowRequest()) { $this->log(sprintf("Closing '%s' workflow request for '%s'", $wf->Status, $page->Title)); $wf->deny('Page automatically expired. Removing from Live site.', $admin); } $page->ExpiryDate = null; $page->write(); $page->doUnpublish(); $this->log(sprintf("Unpublished '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); } catch (Exception $e) { $this->log(sprintf("Failed to unpublish '%s' (URL: %s)", $page->Title, $page->AbsoluteLink())); user_error("Error unpublishing Page ID " . $page->ID . " - " . $page->Title . " Error: " . $e->getMessage(), E_USER_WARNING); continue; } } } // We don't need to clear the lock on every potential exception, // as the closing of the DB connection will do that for us. if (method_exists($db, 'supportsLocks') && $db->supportsLocks()) { $db->releaseLock('ScheduledPublishing'); } }
public function init() { $origDisableSubsiteFilter = Subsite::$disable_subsite_filter; Subsite::$disable_subsite_filter = true; parent::init(); Subsite::$disable_subsite_filter = $origDisableSubsiteFilter; }
/** * This function ensures the file table is correct with the files in the assets folder. * * If a Folder record ID is given, all of that folder's children will be synchronised. * If the given Folder ID isn't found, or not specified at all, then everything will * be synchronised from the root folder (singleton Folder). * * See {@link File->updateFilesystem()} to sync properties of a single database record * back to the equivalent filesystem record. * * @param int $folderID Folder ID to sync along with all it's children * @param Boolean $syncLinkTracking Determines if the link tracking data should also * be updated via {@link SiteTree->syncLinkTracking()}. Setting this to FALSE * means that broken links inside page content are not noticed, at least until the next * call to {@link SiteTree->write()} on this page. * @return string Localized status message */ static function sync($folderID = null, $syncLinkTracking = true) { $folder = DataObject::get_by_id('Folder', (int) $folderID); if(!($folder && $folder->exists())) $folder = singleton('Folder'); $results = $folder->syncChildren(); $finished = false; while(!$finished) { $orphans = DB::query("SELECT \"C\".\"ID\" FROM \"File\" AS \"C\" LEFT JOIN \"File\" AS \"P\" ON \"C\".\"ParentID\" = \"P\".\"ID\" WHERE \"P\".\"ID\" IS NULL AND \"C\".\"ParentID\" > 0"); $finished = true; if($orphans) foreach($orphans as $orphan) { $finished = false; // Delete the database record but leave the filesystem alone $file = DataObject::get_by_id("File", $orphan['ID']); $file->deleteDatabaseOnly(); unset($file); } } // Update the image tracking of all pages if($syncLinkTracking) { if(class_exists('SiteTree')) { if(class_exists('Subsite')) $origDisableSubsiteFilter = Subsite::$disable_subsite_filter; if(class_exists('Subsite')) Subsite::$disable_subsite_filter = true; foreach(DataObject::get("SiteTree") as $page) { // syncLinkTracking is called by SiteTree::onBeforeWrite(). // Call it without affecting the page version, as this is an internal change. $page->writeWithoutVersion(); } if(class_exists('Subsite')) Subsite::disable_subsite_filter($origDisableSubsiteFilter); } } return _t( 'Filesystem.SYNCRESULTS', sprintf('Sync complete: %s items created, %d items deleted', (int) $results['added'], (int) $results['deleted']) ); }
/** * Rewrite links to the $old file to now point to the $new file. * * @uses SiteTree->rewriteFileID() */ public function updateLinks() { if (class_exists('Subsite')) { Subsite::disable_subsite_filter(true); } $pages = $this->owner->BackLinkTracking(); if ($pages) { foreach ($pages as $page) { $page->rewriteFileLinks(); } } if (class_exists('Subsite')) { Subsite::disable_subsite_filter(false); } }
/** * Returns the pages that depend on this page. This includes virtual pages, pages that link to it, etc. * * @param bool $includeVirtuals Set to false to exlcude virtual pages. * @return ArrayList */ public function DependentPages($includeVirtuals = true) { if (class_exists('Subsite')) { $origDisableSubsiteFilter = Subsite::$disable_subsite_filter; Subsite::disable_subsite_filter(true); } // Content links $items = new ArrayList(); // We merge all into a regular SS_List, because DataList doesn't support merge if ($contentLinks = $this->BackLinkTracking()) { $linkList = new ArrayList(); foreach ($contentLinks as $item) { $item->DependentLinkType = 'Content link'; $linkList->push($item); } $items->merge($linkList); } // Virtual pages if ($includeVirtuals) { $virtuals = $this->VirtualPages(); if ($virtuals) { $virtualList = new ArrayList(); foreach ($virtuals as $item) { $item->DependentLinkType = 'Virtual page'; $virtualList->push($item); } $items->merge($virtualList); } } // Redirector pages $redirectors = DataObject::get("RedirectorPage", "\"RedirectorPage\".\"RedirectionType\" = 'Internal' AND \"LinkToID\" = {$this->ID}"); if ($redirectors) { $redirectorList = new ArrayList(); foreach ($redirectors as $item) { $item->DependentLinkType = 'Redirector page'; $redirectorList->push($item); } $items->merge($redirectorList); } if (class_exists('Subsite')) { Subsite::disable_subsite_filter($origDisableSubsiteFilter); } return $items; }