public function testVersionedCache() { $origReadingMode = Versioned::get_reading_mode(); // Run without caching in stage to prove data is uncached $this->_reset(false); Versioned::set_stage(Versioned::DRAFT); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('default'); $this->assertEquals('default Stage.Stage', SSViewer::execute_string('<% cached %>$Inspect<% end_cached %>', $data)); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('first'); $this->assertEquals('first Stage.Stage', SSViewer::execute_string('<% cached %>$Inspect<% end_cached %>', $data)); // Run without caching in live to prove data is uncached $this->_reset(false); Versioned::set_stage(Versioned::LIVE); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('default'); $this->assertEquals('default Stage.Live', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('first'); $this->assertEquals('first Stage.Live', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); // Then with caching, initially in draft, and then in live, to prove that // changing the versioned reading mode doesn't cache between modes, but it does // within them $this->_reset(true); Versioned::set_stage(Versioned::DRAFT); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('default'); $this->assertEquals('default Stage.Stage', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('first'); $this->assertEquals('default Stage.Stage', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); Versioned::set_stage(Versioned::LIVE); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('first'); $this->assertEquals('first Stage.Live', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); $data = new SSViewerCacheBlockTest_VersionedModel(); $data->setEntropy('second'); $this->assertEquals('first Stage.Live', $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data)); Versioned::set_reading_mode($origReadingMode); }
public function setUp() { parent::setUp(); Director::config()->update('rules', array('FormTest_Controller' => 'FormTest_Controller')); // Suppress themes SSViewer::config()->remove('theme'); }
public function getHTMLFragments($gridField) { $count = $gridField->getList()->count(); $forTemplate = new ArrayData(array('ShowRecordCount' => $this->showrecordcount, 'Message' => $this->message, 'FirstShownRecord' => 1, 'LastShownRecord' => $count, 'NumRecords' => $count)); $template = SSViewer::get_templates_by_class($this, '', __CLASS__); return array('footer' => $forTemplate->renderWith($template, array('Colspan' => count($gridField->getColumns())))); }
/** * Small helper to render templates from strings * Cloned from SSViewerTest */ private function render($templateString, $data = null) { $t = SSViewer::fromString($templateString); if (!$data) { $data = new SSViewerTestFixture(); } return $t->process($data); }
public function getColumnContent($field, $record, $col) { if (!$record->canView()) { return null; } $data = new ArrayData(array('Link' => Controller::join_links($field->Link('item'), $record->ID, 'view'))); $template = SSViewer::get_templates_by_class($this, '', __CLASS__); return $data->renderWith($template); }
/** * @param GridField $gridField * @return array */ public function getHTMLFragments($gridField) { // Retrieve paging parameters from the directing paginator component $paginator = $this->getPaginator($gridField); if ($paginator && ($forTemplate = $paginator->getTemplateParameters($gridField))) { $template = SSViewer::get_templates_by_class($this, '', __CLASS__); return array($this->targetFragment => $forTemplate->renderWith($template)); } return null; }
public function getHTMLFragments($gridField) { $singleton = singleton($gridField->getModelClass()); if (!$singleton->canCreate()) { return array(); } if (!$this->buttonName) { // provide a default button name, can be changed by calling {@link setButtonName()} on this component $objectName = $singleton->i18n_singular_name(); $this->buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName)); } $data = new ArrayData(array('NewLink' => Controller::join_links($gridField->Link('item'), 'new'), 'ButtonName' => $this->buttonName)); $templates = SSViewer::get_templates_by_class($this, '', __CLASS__); return array($this->targetFragment => $data->renderWith($templates)); }
public function setUp() { // Skip calling FunctionalTest directly. if (get_class($this) == __CLASS__) { $this->markTestSkipped(sprintf('Skipping %s ', get_class($this))); } parent::setUp(); $this->mainSession = new TestSession(); // Disable theme, if necessary if (static::get_disable_themes()) { SSViewer::config()->update('theme_enabled', false); } // Switch to draft site, if necessary if (static::get_use_draft_site()) { $this->useDraftSite(); } // Unprotect the site, tests are running with the assumption it's off. They will enable it on a case-by-case // basis. BasicAuth::protect_entire_site(false); SecurityToken::disable(); }
public function getHTMLFragments($gridField) { $modelClass = $gridField->getModelClass(); $parentID = 0; if (!$this->currentID) { return null; } $modelObj = DataObject::get_by_id($modelClass, $this->currentID); $parent = null; if ($modelObj->hasMethod('getParent')) { $parent = $modelObj->getParent(); } elseif ($modelObj->ParentID) { $parent = $modelObj->Parent(); } if ($parent) { $parentID = $parent->ID; } // Attributes $attrs = array_merge($this->attributes, array('href' => sprintf($this->linkSpec, $parentID), 'class' => 'cms-panel-link ss-ui-button font-icon-level-up no-text grid-levelup')); $linkTag = FormField::create_tag('a', $attrs); $forTemplate = new ArrayData(array('UpLink' => DBField::create_field('HTMLFragment', $linkTag))); $template = SSViewer::get_templates_by_class($this, '', __CLASS__); return array('before' => $forTemplate->renderWith($template)); }
/** * Test against a theme. * * @param string $themeBaseDir themes directory * @param string $theme Theme name * @param callable $callback * @throws Exception */ protected function useTestTheme($themeBaseDir, $theme, $callback) { Config::nest(); if (strpos($themeBaseDir, BASE_PATH) === 0) { $themeBaseDir = substr($themeBaseDir, strlen(BASE_PATH)); } SSViewer::config()->update('theme_enabled', true); SSViewer::set_themes([$themeBaseDir . '/themes/' . $theme, '$default']); $e = null; try { $callback(); } catch (Exception $e) { /* NOP for now, just save $e */ } Config::unnest(); if ($e) { throw $e; } }
function CacheBlock_CacheBlockTemplate(&$res, $sub) { // Get the block counter $block = ++$res['subblocks']; // Build the key for this block from the global key (evaluated in a closure within the template), // the passed cache key, the block index, and the sha hash of the template. $res['php'] .= '$keyExpression = function() use ($scope, $cache) {' . PHP_EOL; $res['php'] .= '$val = \'\';' . PHP_EOL; if ($globalKey = SSViewer::config()->get('global_key')) { // Embed the code necessary to evaluate the globalKey directly into the template, // so that SSTemplateParser only needs to be called during template regeneration. // Warning: If the global key is changed, it's necessary to flush the template cache. $parser = Injector::inst()->get(__CLASS__, false); $result = $parser->compileString($globalKey, '', false, false); if (!$result) { throw new SSTemplateParseException('Unexpected problem parsing template', $parser); } $res['php'] .= $result . PHP_EOL; } $res['php'] .= 'return $val;' . PHP_EOL; $res['php'] .= '};' . PHP_EOL; $key = 'sha1($keyExpression())' . '.\'_' . sha1($sub['php']) . (isset($res['key']) && $res['key'] ? "_'.sha1(" . $res['key'] . ")" : "'") . ".'_{$block}'"; // block index // Get any condition $condition = isset($res['condition']) ? $res['condition'] : ''; $res['php'] .= 'if (' . $condition . '($partial = $cache->load(' . $key . '))) $val .= $partial;' . PHP_EOL; $res['php'] .= 'else { $oldval = $val; $val = "";' . PHP_EOL; $res['php'] .= $sub['php'] . PHP_EOL; $res['php'] .= $condition . ' $cache->save($val); $val = $oldval . $val;' . PHP_EOL; $res['php'] .= '}'; }
/** * Returns a json array of a search results that can be used by for example Jquery.ui.autosuggestion * * @param GridField $gridField * @param HTTPRequest $request * @return string */ public function doSearch($gridField, $request) { $dataClass = $gridField->getModelClass(); $allList = $this->searchList ? $this->searchList : DataList::create($dataClass); $searchFields = $this->getSearchFields() ? $this->getSearchFields() : $this->scaffoldSearchFields($dataClass); if (!$searchFields) { throw new LogicException(sprintf('GridFieldAddExistingAutocompleter: No searchable fields could be found for class "%s"', $dataClass)); } $params = array(); foreach ($searchFields as $searchField) { $name = strpos($searchField, ':') !== FALSE ? $searchField : "{$searchField}:StartsWith"; $params[$name] = $request->getVar('gridfield_relationsearch'); } $results = $allList->subtract($gridField->getList())->filterAny($params)->sort(strtok($searchFields[0], ':'), 'ASC')->limit($this->getResultsLimit()); $json = array(); Config::nest(); SSViewer::config()->update('source_file_comments', false); $viewer = SSViewer::fromString($this->resultsFormat); foreach ($results as $result) { $title = html_entity_decode($viewer->process($result)); $json[] = array('label' => $title, 'value' => $title, 'id' => $result->ID); } Config::unnest(); return Convert::array2json($json); }
/** * @param GridField $gridField * @param DataObject $record * @param string $columnName * @return string The HTML for the column */ public function getColumnContent($gridField, $record, $columnName) { // No permission checks, handled through GridFieldDetailForm, // which can make the form readonly if no edit permissions are available. $data = new ArrayData(array('Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit'))); $template = SSViewer::get_templates_by_class($this, '', __CLASS__); return $data->renderWith($template); }
/** * Render this object into the template, and get the result as a string. You can pass one of the following as the * $template parameter: * - a template name (e.g. Page) * - an array of possible template names - the first valid one will be used * - an SSViewer instance * * @param string|array|SSViewer $template the template to render into * @param array $customFields fields to customise() the object with before rendering * @return DBHTMLText */ public function renderWith($template, $customFields = null) { if (!is_object($template)) { $template = new SSViewer($template); } $data = $this->customisedObject ? $this->customisedObject : $this; if ($customFields instanceof ViewableData) { $data = $data->customise($customFields); } if ($template instanceof SSViewer) { return $template->process($data, is_array($customFields) ? $customFields : null); } throw new UnexpectedValueException("ViewableData::renderWith(): unexpected " . get_class($template) . " object, expected an SSViewer instance"); }
/** * Render this form using the given template, and return the result as a string * You can pass either an SSViewer or a template name * @param string|array $template * @return DBHTMLText */ public function renderWithoutActionButton($template) { $custom = $this->customise(array("Actions" => "")); if (is_string($template)) { $template = new SSViewer($template); } return $template->process($custom); }
/** * Generate an array of class name strings to use for rendering this form field into HTML. * * @param string $customTemplate * @param string $customTemplateSuffix * * @return array */ protected function _templates($customTemplate = null, $customTemplateSuffix = null) { $templates = SSViewer::get_templates_by_class(get_class($this), $customTemplateSuffix, __CLASS__); // Prefer any custom template if ($customTemplate) { // Prioritise direct template array_unshift($templates, $customTemplate); } return $templates; }
/** * @return string */ public function getTemplateViewFile() { return SSViewer::get_templates_by_class(get_class($this), '_viewfile', __CLASS__); }
/** * Get list of templates to use * * @return array */ public function getTemplates() { $templates = SSViewer::get_templates_by_class($this, '', __CLASS__); // Prefer any custom template if ($this->getTemplate()) { array_unshift($templates, $this->getTemplate()); } return $templates; }
public function testRequireCallInTemplateInclude() { //TODO undo skip test on the event that templates ever obtain the ability to reference MODULE_DIR (or something to that effect) if (FRAMEWORK_DIR === 'framework') { $template = new SSViewer(array('SSViewerTestProcess')); Requirements::set_suffix_requirements(false); $this->assertEquals(1, substr_count($template->process(array()), "tests/javascript/forms/RequirementsTest_a.js")); } else { $this->markTestSkipped('Requirement will always fail if the framework dir is not ' . 'named \'framework\', since templates require hard coded paths'); } }
/** * Return a {@link FieldList} of fields that would appropriate for editing * this member. * * @return FieldList Return a FieldList of fields that would appropriate for * editing this member. */ public function getCMSFields() { require_once 'Zend/Date.php'; $self = $this; $this->beforeUpdateCMSFields(function (FieldList $fields) use($self) { /** @var FieldList $mainFields */ $mainFields = $fields->fieldByName("Root")->fieldByName("Main")->getChildren(); // Build change password field $mainFields->replaceField('Password', $self->getMemberPasswordField()); $mainFields->replaceField('Locale', new DropdownField("Locale", _t('Member.INTERFACELANG', "Interface Language", 'Language of the CMS'), i18n::get_existing_translations())); $mainFields->removeByName($self->config()->hidden_fields); if (!$self->config()->lock_out_after_incorrect_logins) { $mainFields->removeByName('FailedLoginCount'); } // Groups relation will get us into logical conflicts because // Members are displayed within group edit form in SecurityAdmin $fields->removeByName('Groups'); // Members shouldn't be able to directly view/edit logged passwords $fields->removeByName('LoggedPasswords'); $fields->removeByName('RememberLoginHashes'); if (Permission::check('EDIT_PERMISSIONS')) { $groupsMap = array(); foreach (Group::get() as $group) { // Listboxfield values are escaped, use ASCII char instead of » $groupsMap[$group->ID] = $group->getBreadcrumbs(' > '); } asort($groupsMap); $fields->addFieldToTab('Root.Main', ListboxField::create('DirectGroups', singleton('SilverStripe\\Security\\Group')->i18n_plural_name())->setSource($groupsMap)->setAttribute('data-placeholder', _t('Member.ADDGROUP', 'Add group', 'Placeholder text for a dropdown'))); // Add permission field (readonly to avoid complicated group assignment logic). // This should only be available for existing records, as new records start // with no permissions until they have a group assignment anyway. if ($self->ID) { $permissionsField = new PermissionCheckboxSetField_Readonly('Permissions', false, 'SilverStripe\\Security\\Permission', 'GroupID', $self->getManyManyComponents('Groups')); $fields->findOrMakeTab('Root.Permissions', singleton('SilverStripe\\Security\\Permission')->i18n_plural_name()); $fields->addFieldToTab('Root.Permissions', $permissionsField); } } $permissionsTab = $fields->fieldByName("Root")->fieldByName('Permissions'); if ($permissionsTab) { $permissionsTab->addExtraClass('readonly'); } $defaultDateFormat = Zend_Locale_Format::getDateFormat(new Zend_Locale($self->Locale)); $dateFormatMap = array('MMM d, yyyy' => Zend_Date::now()->toString('MMM d, yyyy'), 'yyyy/MM/dd' => Zend_Date::now()->toString('yyyy/MM/dd'), 'MM/dd/yyyy' => Zend_Date::now()->toString('MM/dd/yyyy'), 'dd/MM/yyyy' => Zend_Date::now()->toString('dd/MM/yyyy')); $dateFormatMap[$defaultDateFormat] = Zend_Date::now()->toString($defaultDateFormat) . sprintf(' (%s)', _t('Member.DefaultDateTime', 'default')); $mainFields->push($dateFormatField = new MemberDatetimeOptionsetField('DateFormat', $self->fieldLabel('DateFormat'), $dateFormatMap)); $formatClass = get_class($dateFormatField); $dateFormatField->setValue($self->DateFormat); $dateTemplate = SSViewer::get_templates_by_class($formatClass, '_description_date', $formatClass); $dateFormatField->setDescriptionTemplate($dateTemplate); $defaultTimeFormat = Zend_Locale_Format::getTimeFormat(new Zend_Locale($self->Locale)); $timeFormatMap = array('h:mm a' => Zend_Date::now()->toString('h:mm a'), 'H:mm' => Zend_Date::now()->toString('H:mm')); $timeFormatMap[$defaultTimeFormat] = Zend_Date::now()->toString($defaultTimeFormat) . sprintf(' (%s)', _t('Member.DefaultDateTime', 'default')); $mainFields->push($timeFormatField = new MemberDatetimeOptionsetField('TimeFormat', $self->fieldLabel('TimeFormat'), $timeFormatMap)); $timeFormatField->setValue($self->TimeFormat); $timeTemplate = SSViewer::get_templates_by_class($formatClass, '_description_time', $formatClass); $timeFormatField->setDescriptionTemplate($timeTemplate); }); return parent::getCMSFields(); }
/** * Get location of all editor.css files * * @return array */ protected function getEditorCSS() { $editor = array(); // Add standard editor.css $editor[] = Director::absoluteURL(FRAMEWORK_ADMIN_DIR . '/client/dist/styles/editor.css'); // Themed editor.css $themedEditor = ThemeResourceLoader::instance()->findThemedCSS('editor', SSViewer::get_themes()); if ($themedEditor) { $editor[] = Director::absoluteURL($themedEditor, Director::BASE); } return $editor; }
/** * Returns TRUE if this controller has a template that is specifically designed to handle a * specific action. * * @param string $action * * @return bool */ public function hasActionTemplate($action) { if (isset($this->templates[$action])) { return true; } $parentClass = $this->class; $templates = array(); while ($parentClass != __CLASS__) { $templates[] = strtok($parentClass, '_') . '_' . $action; $parentClass = get_parent_class($parentClass); } return SSViewer::hasTemplate($templates); }
/** * Renders a panel containing tools which apply to the currently displayed edit form. * The main difference to {@link Tools()} is that the panel is displayed within * the element structure of the form panel (rendered through {@link EditForm}). * This means the panel will be loaded alongside new forms, and refreshed upon save, * which can mean a performance hit, depending on how complex your panel logic gets. * Any form fields contained in the returned markup will also be submitted with the main form, * which might be desired depending on the implementation details. * * @return String HTML */ public function EditFormTools() { $templates = $this->getTemplatesWithSuffix('_EditFormTools'); if ($templates) { $viewer = new SSViewer($templates); return $viewer->process($this); } else { return false; } }
/** * @param GridField $gridField * @return array */ public function getHTMLFragments($gridField) { $templates = SSViewer::get_templates_by_class($this, '', __CLASS__); return array('header' => $gridField->renderWith($templates)); }
/** * Returns the header row providing titles with sort buttons * * @param GridField $gridField * @return array */ public function getHTMLFragments($gridField) { $list = $gridField->getList(); if (!$this->checkDataType($list)) { return null; } /** @var Sortable $list */ $forTemplate = new ArrayData(array()); $forTemplate->Fields = new ArrayList(); $state = $gridField->State->GridFieldSortableHeader; $columns = $gridField->getColumns(); $currentColumn = 0; $schema = DataObject::getSchema(); foreach ($columns as $columnField) { $currentColumn++; $metadata = $gridField->getColumnMetadata($columnField); $fieldName = str_replace('.', '-', $columnField); $title = $metadata['title']; if (isset($this->fieldSorting[$columnField]) && $this->fieldSorting[$columnField]) { $columnField = $this->fieldSorting[$columnField]; } $allowSort = $title && $list->canSortBy($columnField); if (!$allowSort && strpos($columnField, '.') !== false) { // we have a relation column with dot notation // @see DataObject::relField for approximation $parts = explode('.', $columnField); $tmpItem = singleton($list->dataClass()); for ($idx = 0; $idx < sizeof($parts); $idx++) { $methodName = $parts[$idx]; if ($tmpItem instanceof SS_List) { // It's impossible to sort on a HasManyList/ManyManyList break; } elseif (method_exists($tmpItem, 'hasMethod') && $tmpItem->hasMethod($methodName)) { // The part is a relation name, so get the object/list from it $tmpItem = $tmpItem->{$methodName}(); } elseif ($tmpItem instanceof DataObject && $schema->fieldSpec($tmpItem, $methodName, DataObjectSchema::DB_ONLY)) { // Else, if we've found a database field at the end of the chain, we can sort on it. // If a method is applied further to this field (E.g. 'Cost.Currency') then don't try to sort. $allowSort = $idx === sizeof($parts) - 1; break; } else { // If neither method nor field, then unable to sort break; } } } if ($allowSort) { $dir = 'asc'; if ($state->SortColumn(null) == $columnField && $state->SortDirection('asc') == 'asc') { $dir = 'desc'; } $field = GridField_FormAction::create($gridField, 'SetOrder' . $fieldName, $title, "sort{$dir}", array('SortColumn' => $columnField))->addExtraClass('grid-field__sort'); if ($state->SortColumn(null) == $columnField) { $field->addExtraClass('ss-gridfield-sorted'); if ($state->SortDirection('asc') == 'asc') { $field->addExtraClass('ss-gridfield-sorted-asc'); } else { $field->addExtraClass('ss-gridfield-sorted-desc'); } } } else { if ($currentColumn == count($columns) && $gridField->getConfig()->getComponentByType('SilverStripe\\Forms\\GridField\\GridFieldFilterHeader')) { $field = new LiteralField($fieldName, '<button type="button" name="showFilter" class="btn font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>'); } else { $field = new LiteralField($fieldName, '<span class="non-sortable">' . $title . '</span>'); } } $forTemplate->Fields->push($field); } $template = SSViewer::get_templates_by_class($this, '_Row', __CLASS__); return array('header' => $forTemplate->renderWith($template)); }
/** * * @param GridField $gridField * @return array */ public function getHTMLFragments($gridField) { $forTemplate = $this->getTemplateParameters($gridField); if (!$forTemplate) { return null; } $template = SSViewer::get_templates_by_class($this, '_Row', __CLASS__); return array('footer' => $forTemplate->renderWith($template, array('Colspan' => count($gridField->getColumns())))); }
/** * Determine the list of templates to use for rendering the given action. * * @skipUpgrade * @param string $action * @return array Template list */ public function getTemplatesFor($action) { $templates = SSViewer::get_templates_by_class(get_class($this), "_{$action}", __CLASS__); return array_merge($templates, ["Security_{$action}", "Security", $this->stat("template_main"), "BlankPage"]); }
public function getHTMLFragments($gridField) { $data = new ArrayData(array("TargetFragmentName" => $this->targetFragment, "LeftFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-left)", "RightFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-right)")); $templates = SSViewer::get_templates_by_class($this, '', __CLASS__); return array($this->targetFragment => $data->renderWith($templates)); }
public function parseTemplateContent($content, $template = "") { return $this->getParser()->compileString($content, $template, Director::isDev() && SSViewer::config()->get('source_file_comments')); }
public function showform() { return "<head>" . SSViewer::get_base_tag("") . "</head>" . $this->Form()->forTemplate(); }