/** * Display a tree of all page types and their children, with perms * * @param Group group show permissions related to this group * @return string A fully formatted tree as a HTML list */ public static function PageTree($group = null) { self::$group = $group; //Get all the page types $classes = SiteTree::page_type_classes(); $pageTreeList = array(); //We don't want to remove the fields from this list, so disable the remove SimplifyPermissionProvider::setRemoveEnabled(false); //Get an instance of each page type, add to an array //TODO: This works, but only returns the initial field state of the objects // Might be a better way to scrape ALL the possible fields? foreach ($classes as $class) { $instance = singleton($class); if ($instance instanceof HiddenClass) { continue; } if (!$instance->canCreate()) { continue; } $pageTreeList[] = $instance; } //Get the children of each page type and return it as an UL $pageTree = self::getChildrenAsUL($pageTreeList, 0, " id='perm-tree' class='tree' ", "SiteTree"); //Re-enable the remove SimplifyPermissionProvider::setRemoveEnabled(true); return $pageTree; }
/** * Returns a sorted array suitable for a dropdown with pagetypes and their translated name. * * @return array */ protected function pageTypeOptions() { $pageTypes = array(); $classes = ArrayLib::valueKey(SiteTree::page_type_classes()); unset($classes['VirtualPage']); unset($classes['ErrorPage']); unset($classes['RedirectorPage']); foreach ($classes as $pageTypeClass) { $pageTypes[$pageTypeClass] = singleton($pageTypeClass)->i18n_singular_name(); } asort($pageTypes); return $pageTypes; }
public function updateExtensibleSearchPageCMSFields(FieldList $fields) { if ($this->owner->SearchEngine === get_class($this)) { $types = SiteTree::page_type_classes(); $source = array_combine($types, $types); // add in any explicitly configured asort($source); $source = $this->owner->updateSource($source); $parsers = $this->owner->getQueryBuilders(); $options = array(); foreach ($parsers as $key => $objCls) { $obj = new $objCls(); $options[$key] = $obj->title; } $fields->addFieldToTab('Root.Main', new DropdownField('QueryType', _t('ExtensibleSearchPage.QUERY_TYPE', 'Query Type'), $options), 'Content'); ksort($source); $source = array_merge($source, ExtensibleSearchPage::config()->additional_search_types); $types = MultiValueDropdownField::create('SearchType', _t('ExtensibleSearchPage.SEARCH_ITEM_TYPE', 'Search items of type'), $source); $fields->addFieldToTab('Root.Main', $types, 'Content'); $objFields = $this->owner->getSelectableFields(); $sortFields = $objFields; // Remove content and groups from being sortable (as they are not relevant). unset($sortFields['Content']); unset($sortFields['Groups']); $fields->replaceField('SortBy', new DropdownField('SortBy', _t('ExtensibleSearchPage.SORT_BY', 'Sort By'), $sortFields)); $fields->addFieldToTab('Root.Main', MultiValueDropdownField::create('SearchOnFields', _t('ExtensibleSearchPage.INCLUDE_FIELDS', 'Search On Fields'), $objFields), 'Content'); $fields->addFieldToTab('Root.Main', MultiValueTextField::create('ExtraSearchFields', _t('SolrSearch.EXTRA_FIELDS', 'Custom solr fields to search')), 'Content'); $boostVals = array(); for ($i = 1; $i <= static::BOOST_MAX; $i++) { $boostVals[$i] = $i; } $fields->addFieldToTab('Root.Main', new KeyValueField('BoostFields', _t('ExtensibleSearchPage.BOOST_FIELDS', 'Boost values'), $objFields, $boostVals), 'Content'); $fields->addFieldToTab('Root.Main', $f = new KeyValueField('BoostMatchFields', _t('ExtensibleSearchPage.BOOST_MATCH_FIELDS', 'Boost fields with field/value matches'), array(), $boostVals), 'Content'); $f->setRightTitle('Enter a field name, followed by the value to boost if found in the result set, eg "title:Home" '); $fields->addFieldToTab('Root.Main', $kv = new KeyValueField('FilterFields', _t('ExtensibleSearchPage.FILTER_FIELDS', 'Fields to filter by')), 'Content'); $fields->addFieldToTab('Root.Main', new HeaderField('FacetHeader', _t('ExtensibleSearchPage.FACET_HEADER', 'Facet Settings')), 'Content'); $fields->addFieldToTab('Root.Main', new MultiValueDropdownField('FacetFields', _t('ExtensibleSearchPage.FACET_FIELDS', 'Fields to create facets for'), $objFields), 'Content'); $fields->addFieldToTab('Root.Main', new MultiValueTextField('CustomFacetFields', _t('ExtensibleSearchPage.CUSTOM_FACET_FIELDS', 'Additional fields to create facets for')), 'Content'); $facetMappingFields = $objFields; if ($this->owner->CustomFacetFields && ($cff = $this->owner->CustomFacetFields->getValues())) { foreach ($cff as $facetField) { $facetMappingFields[$facetField] = $facetField; } } $fields->addFieldToTab('Root.Main', new KeyValueField('FacetMapping', _t('ExtensibleSearchPage.FACET_MAPPING', 'Mapping of facet title to nice title'), $facetMappingFields), 'Content'); $fields->addFieldToTab('Root.Main', new KeyValueField('FacetQueries', _t('ExtensibleSearchPage.FACET_QUERIES', 'Fields to create query facets for')), 'Content'); $fields->addFieldToTab('Root.Main', new NumericField('MinFacetCount', _t('ExtensibleSearchPage.MIN_FACET_COUNT', 'Minimum facet count for inclusion in facet results'), 2), 'Content'); } // Make sure previously existing hooks are carried across. $this->owner->extend('updateSolrCMSFields', $fields); }
public function getCMSFields() { $fields = parent::getCMSFields(); $fields->removeByName('ExcludeItems'); $fields->removeByName('SourceID'); $pageClasses = SiteTree::page_type_classes(); $pageTypes = array(); foreach ($pageClasses as $class) { $pageTypes[$class] = singleton($class)->i18n_singular_name(); } $fields->addFieldsToTab('Root.Main', array(CheckboxField::create('EnforceShowInMenu', _t('ChildPageListBlock.EXCLUDEITEMSNOTINMENUS', "Exclude items which don't show in menus")), MultiValueListField::create('PageTypes', _t('ChildPageListBock.ONLYINCLUDETYPES', 'Only include these page types'), $pageTypes)->setRightTitle('Leave blank to include all types'), OptionsetField::create('AbsoluteSource', _t('ChildPageListBock.SOURCEOPTION', 'Source option'), array(false => _t('ChildPageListBock.SOURCECURRENTPAGE', 'Current page being viewed'), true => _t('ChildPageListBock.SOURCESPECIFICPAGE', 'A specific page'))), TreeDropdownField::create('SourceID', _t('ChildPageListBock.SOURCEPAGE', 'Source page'), 'SiteTree')->displayIf("AbsoluteSource")->isEqualTo(1)->end())); if ($this->AbsoluteSource) { $kids = $this->Source()->AllChildren(); if ($kids && $kids->Count()) { $fields->addFieldToTab('Root.Main', MultiValueListField::create('ExcludeItems', _t('ChildPageListBock.EXCLUDECHILDREN', 'Exclude these children'), $kids->map('ID', 'Title'))->displayIf("AbsoluteSource")->isEqualTo(1)->end()); } } return $fields; }
/** * Determine the list of classnames and titles allowed for a given parent object * * @param SiteTree $parent * @return boolean */ public function getAllowedChildren(SiteTree $parent = null) { if (!$parent || !$parent->canAddChildren()) { return array(); } $nonHiddenPageTypes = SiteTree::page_type_classes(); $allowedChildren = $parent->allowedChildren(); $children = array(); foreach ($allowedChildren as $class) { if (Config::inst()->get($class, "show_in_sitetree") === false) { $instance = Injector::inst()->get($class); // Note: Second argument to SiteTree::canCreate will support inherited permissions // post 3.1.12, and will default to the old permission model in 3.1.11 or below // See http://docs.silverstripe.org/en/changelogs/3.1.11 if ($instance->canCreate(null, array('Parent' => $parent)) && in_array($class, $nonHiddenPageTypes)) { $children[$class] = $instance->i18n_singular_name(); } } } return $children; }
public function testPageTypeClasses() { $classes = SiteTree::page_type_classes(); $this->assertNotContains('SiteTree', $classes, 'Page types do not include base class'); $this->assertContains('Page', $classes, 'Page types do contain subclasses'); }
/** * Populates an array of classes in the CMS * which allows the user to change the page type. * * @return DataObjectSet */ public function PageTypes() { $classes = SiteTree::page_type_classes(); $result = new DataObjectSet(); foreach ($classes as $class) { $instance = singleton($class); if ($instance instanceof HiddenClass) { continue; } if (!$instance->canCreate()) { continue; } // skip this type if it is restricted if ($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) { continue; } $addAction = $instance->i18n_singular_name(); // if we're in translation mode, the link between the translated pagetype // title and the actual classname might not be obvious, so we add it in parantheses // Example: class "RedirectorPage" has the title "Weiterleitung" in German, // so it shows up as "Weiterleitung (RedirectorPage)" if (i18n::get_locale() != 'en_US') { $addAction .= " ({$class})"; } $result->push(new ArrayData(array('ClassName' => $class, 'AddAction' => $addAction))); } $result->sort('AddAction'); return $result; }
/** * Form used to filter the sitetree. It can only be used via javascript for now. * * @return Form */ function SearchTreeForm() { // get all page types in a dropdown-compatible format $pageTypes = SiteTree::page_type_classes(); array_unshift($pageTypes, 'All'); $pageTypes = array_combine($pageTypes, $pageTypes); asort($pageTypes); // get all filter instances $filters = ClassInfo::subclassesFor('CMSSiteTreeFilter'); $filterMap = array(); // remove base class array_shift($filters); // add filters to map foreach ($filters as $filter) { $filterMap[$filter] = call_user_func(array($filter, 'title')); } // ensure that 'all pages' filter is on top position uasort($filterMap, create_function('$a,$b', 'return ($a == "CMSSiteTreeFilter_Search") ? 1 : -1;')); $showDefaultFields = array(); $form = new Form($this, 'SearchTreeForm', new FieldSet($showDefaultFields[] = new DropdownField('FilterClass', _t('CMSMain.SearchTreeFormPagesDropdown', 'Pages'), $filterMap), $showDefaultFields[] = new TextField('Title', _t('CMSMain.TITLEOPT', 'Title')), new TextField('Content', 'Text'), new DateField('EditedSince', _t('CMSMain_left.ss.EDITEDSINCE', 'Edited Since')), new DropdownField('ClassName', 'Page Type', $pageTypes, null, null, 'Any'), new TextField('MenuTitle', _t('CMSMain.MENUTITLEOPT', 'Navigation Label')), new TextField('Status', _t('CMSMain.STATUSOPT', 'Status')), new TextField('MetaDescription', _t('CMSMain.METADESCOPT', 'Description')), new TextField('MetaKeywords', _t('CMSMain.METAKEYWORDSOPT', 'Keywords'))), new FieldSet(new ResetFormAction('clear', _t('CMSMain_left.ss.CLEAR', 'Clear')), new FormAction('doSearchTree', _t('CMSMain_left.ss.SEARCH', 'Search')))); $form->setFormMethod('GET'); $form->disableSecurityToken(); $form->unsetValidator(); foreach ($showDefaultFields as $f) { $f->addExtraClass('show-default'); } return $form; }
/** * Populates an array of classes in the CMS * which allows the user to change the page type. * * @return SS_List */ public function PageTypes() { $classes = SiteTree::page_type_classes(); $result = new ArrayList(); foreach ($classes as $class) { $instance = singleton($class); if ($instance instanceof HiddenClass) { continue; } if (!$instance->canCreate()) { continue; } // skip this type if it is restricted if ($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) { continue; } $addAction = $instance->i18n_singular_name(); // Get description (convert 'Page' to 'SiteTree' for correct localization lookups) $description = _t(($class == 'Page' ? 'SiteTree' : $class) . '.DESCRIPTION'); if (!$description) { $description = $instance->uninherited('description'); } if ($class == 'Page' && !$description) { $description = singleton('SiteTree')->uninherited('description'); } $result->push(new ArrayData(array('ClassName' => $class, 'AddAction' => $addAction, 'Description' => $description, 'IconURL' => $instance->stat('icon'), 'Title' => singleton($class)->i18n_singular_name()))); } $result = $result->sort('AddAction'); return $result; }
/** * Callback to request the list of page types allowed under a given page instance. * Provides a slower but more precise response over SiteTreeHints * * @param SS_HTTPRequest $request * @return SS_HTTPResponse */ public function childfilter($request) { // Check valid parent specified $parentID = $request->requestVar('ParentID'); $parent = SiteTree::get()->byID($parentID); if (!$parent || !$parent->exists()) { return $this->httpError(404); } // Build hints specific to this class // Identify disallows and set globals $classes = SiteTree::page_type_classes(); $disallowedChildren = array(); foreach ($classes as $class) { $obj = singleton($class); if ($obj instanceof HiddenClass) { continue; } if (!$obj->canCreate(null, array('Parent' => $parent))) { $disallowedChildren[] = $class; } } $this->extend('updateChildFilter', $disallowedChildren, $parentID); return $this->response->addHeader('Content-Type', 'application/json; charset=utf-8')->setBody(Convert::raw2json($disallowedChildren)); }
public function testPageTypeClasses() { $classes = SiteTree::page_type_classes(); $this->assertNotContains('SiteTree', $classes, 'Page types do not include base class'); $this->assertContains('Page', $classes, 'Page types do contain subclasses'); // Testing what happens in an incorrect config value is set - hide_ancestor should be a string Config::inst()->update('SiteTreeTest_ClassA', 'hide_ancestor', true); $newClasses = SiteTree::page_type_classes(); $this->assertEquals($classes, $newClasses, 'Setting hide_ancestor to a boolean (incorrect) value caused a page class to be hidden'); }
/** * Show the configuration fields for each subsite * * @return FieldList */ public function getCMSFields() { if ($this->ID != 0) { $domainTable = new GridField("Domains", _t('Subsite.DomainsListTitle', "Domains"), $this->Domains(), GridFieldConfig_RecordEditor::create(10)); } else { $domainTable = new LiteralField('Domains', '<p>' . _t('Subsite.DOMAINSAVEFIRST', 'You can only add domains after saving for the first time') . '</p>'); } $languageSelector = new DropdownField('Language', $this->fieldLabel('Language'), i18n::get_common_locales()); $pageTypeMap = array(); $pageTypes = SiteTree::page_type_classes(); foreach ($pageTypes as $pageType) { $pageTypeMap[$pageType] = singleton($pageType)->i18n_singular_name(); } asort($pageTypeMap); $fields = new FieldList($subsiteTabs = new TabSet('Root', new Tab('Configuration', _t('Subsite.TabTitleConfig', 'Configuration'), new HeaderField($this->getClassName() . ' configuration', 2), new TextField('Title', $this->fieldLabel('Title'), $this->Title), new HeaderField(_t('Subsite.DomainsHeadline', "Domains for this subsite")), $domainTable, $languageSelector, new CheckboxField('DefaultSite', $this->fieldLabel('DefaultSite'), $this->DefaultSite), new CheckboxField('IsPublic', $this->fieldLabel('IsPublic'), $this->IsPublic), new DropdownField('Theme', $this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme), new LiteralField('PageTypeBlacklistToggle', sprintf('<div class="field"><a href="#" id="PageTypeBlacklistToggle">%s</a></div>', _t('Subsite.PageTypeBlacklistField', 'Disallow page types?'))), new CheckboxSetField('PageTypeBlacklist', false, $pageTypeMap))), new HiddenField('ID', '', $this->ID), new HiddenField('IsSubsite', '', 1)); $subsiteTabs->addExtraClass('subsite-model'); $this->extend('updateCMSFields', $fields); return $fields; }
/** * Show the configuration fields for each subsite * * @return FieldList */ public function getCMSFields() { if ($this->ID != 0) { $domainTable = new GridField("Domains", _t('Subsite.DomainsListTitle', "Domains"), $this->Domains(), GridFieldConfig_RecordEditor::create(10)); } else { $domainTable = new LiteralField('Domains', '<p>' . _t('Subsite.DOMAINSAVEFIRST', 'You can only add domains after saving for the first time') . '</p>'); } $languageSelector = new TextField('Language', $this->fieldLabel('Language')); $pageTypeMap = array(); $pageTypes = SiteTree::page_type_classes(); foreach ($pageTypes as $pageType) { $pageTypeMap[$pageType] = singleton($pageType)->i18n_singular_name(); } asort($pageTypeMap); $fields = new FieldList($subsiteTabs = new TabSet('Root', new Tab('Configuration', _t('Subsite.TabTitleConfig', 'Configuration'), new HeaderField($this->getClassName() . ' configuration', 2), new TextField('Title', $this->fieldLabel('Title'), $this->Title), new HeaderField(_t('Subsite.DomainsHeadline', "Domains for this subsite")), $domainTable, $languageSelector, new DropdownField('Theme', $this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme))), new HiddenField('ID', '', $this->ID), new HiddenField('IsSubsite', '', 1)); $subsiteTabs->addExtraClass('subsite-model'); $this->extend('updateCMSFields', $fields); return $fields; }
/** * Populates an array of classes in the CMS * which allows the user to change the page type. * * @return SS_List */ public function PageTypes() { $classes = SiteTree::page_type_classes(); $result = new ArrayList(); foreach($classes as $class) { $instance = singleton($class); if($instance instanceof HiddenClass) continue; if(!$instance->canCreate()) continue; // skip this type if it is restricted if($instance->stat('need_permission') && !$this->can(singleton($class)->stat('need_permission'))) continue; $addAction = $instance->i18n_singular_name(); // Get description $description = _t($class . 'DESCRIPTION'); if(!$description) $description = $instance->uninherited('description'); if($class == 'Page' && !$description) $description = singleton('SiteTree')->uninherited('description'); $result->push(new ArrayData(array( 'ClassName' => $class, 'AddAction' => $addAction, 'Description' => $description, // TODO Sprite support 'IconURL' => $instance->stat('icon') ))); } $result->sort('AddAction'); return $result; }
public function ListOfAllClasses($checkCurrentClass = true) { if (!self::$list_of_all_classes) { $ArrayOfAllClasses = array(); //$classes = ClassInfo::subclassesFor("SiteTree"); $classes = SiteTree::page_type_classes(); $classesToRemove = array(); foreach ($classes as $className) { if (!in_array($className, $this->config()->get("classes_to_exclude"))) { if ($this->showAll) { $objects = $className::get()->filter(array("ClassName" => $className))->sort("RAND() ASC")->limit(25); $count = 0; if ($objects->count()) { foreach ($objects as $obj) { if (!$count) { if ($ancestorToHide = $obj->stat('hide_ancestor')) { $classesToRemove[] = $ancestorToHide; } } $object = $this->createPageObject($obj, $count++); $ArrayOfAllClasses[$object->indexNumber] = clone $object; } } } else { $obj = null; $obj = $className::get()->filter(array("ClassName" => $className))->sort("RAND() ASC")->limit(1)->first(); if ($obj) { $count = SiteTree::get()->filter(array("ClassName" => $obj->ClassName))->count(); } else { $obj = $className::create(); $count = 0; } if ($ancestorToHide = $obj->stat('hide_ancestor')) { $classesToRemove[] = $ancestorToHide; } $object = $this->createPageObject($obj, $count); $object->TemplateOverviewDescription = $this->TemplateDetails($className); $ArrayOfAllClasses[$object->indexNumber] = clone $object; } } } //remove the hidden ancestors... if ($classesToRemove && count($classesToRemove)) { $classesToRemove = array_unique($classesToRemove); // unset from $classes foreach ($ArrayOfAllClasses as $tempKey => $tempClass) { if (in_array($tempClass->ClassName, $classesToRemove)) { unset($ArrayOfAllClasses[$tempKey]); } } } ksort($ArrayOfAllClasses); self::$list_of_all_classes = new ArrayList(); $currentClassname = ''; if ($checkCurrentClass) { if ($c = Controller::curr()) { if ($d = $c->dataRecord) { $currentClassname = $d->ClassName; } } } if (count($ArrayOfAllClasses)) { foreach ($ArrayOfAllClasses as $item) { if ($item->ClassName == $currentClassname) { $item->LinkingMode = "current"; } else { $item->LinkingMode = "link"; } self::$list_of_all_classes->push($item); } } } return self::$list_of_all_classes; }
public function getCMSFields() { $fields = parent::getCMSFields(); Requirements::css(EXTENSIBLE_SEARCH_PATH . '/css/extensible-search.css'); // Restrict the search suggestion approval appropriately. $user = Member::currentUserID(); if (Permission::checkMember($user, 'EXTENSIBLE_SEARCH_SUGGESTIONS')) { Requirements::javascript(EXTENSIBLE_SEARCH_PATH . '/javascript/extensible-search-approval.js'); } // Determine if full text search is enabled. $engines = array('' => ''); $searchable = Config::inst()->get('FulltextSearchable', 'searchable_classes'); if (is_array($searchable) && count($searchable) > 0) { $engines['Full-Text'] = 'Full-Text'; } // Retrieve a list of search engine extensions currently applied that end with 'Search'. $extensions = $this->get_extensions(get_class()); foreach ($extensions as $extension) { $reversed = strrev($extension); if (strpos($reversed, strrev('Search')) === 0) { $engine = strrev(substr($reversed, 6)); $engines[$engine] = $engine; } } // Allow selection of the search engine extension to use. $fields->addFieldToTab('Root.Main', new DropdownField('SearchEngine', 'Search Engine', $engines), 'Content'); // Make sure a search engine is being used before allowing customisation. if ($this->SearchEngine) { // Construct the support array to determine the CMS customisation available to the current search engine/wrapper. $support = self::$support; if ($this->SearchEngine !== 'Full-Text' && $this->extension_instances) { $engine = "{$this->SearchEngine}Search"; foreach ($this->extension_instances as $instance) { if (get_class($instance) === $engine) { $instance->setOwner($this); if (isset($instance::$support)) { $support = array_merge($support, $instance::$support); } $instance->clearOwner(); break; } } } // Use the support array to determine the CMS customisation available to the current search engine/wrapper. if ($support['StartWithListing']) { $fields->addFieldToTab('Root.Main', new CheckboxField('StartWithListing', _t('ExtensibleSearchPage.START_LISTING', 'Display initial listing - useful for filterable "data type" lists')), 'Content'); } if (class_exists('ListingTemplate') && $support['ListingTemplateID']) { $templates = DataObject::get('ListingTemplate'); if ($templates) { $templates = $templates->map(); } else { $templates = array(); } $label = _t('ExtensibleSearchPage.CONTENT_TEMPLATE', 'Listing Template - if not set, theme template will be used'); $fields->addFieldToTab('Root.Main', $template = DropdownField::create('ListingTemplateID', $label, $templates, '', null)->setEmptyString('(results template)'), 'Content'); $template->setEmptyString('(results template)'); } if ($support['ResultsPerPage']) { $perPage = array('5' => '5', '10' => '10', '15' => '15', '20' => '20'); $fields->addFieldToTab('Root.Main', new DropdownField('ResultsPerPage', _t('ExtensibleSearchPage.RESULTS_PER_PAGE', 'Results per page'), $perPage), 'Content'); } if ($support['SearchTrees']) { $fields->addFieldToTab('Root.Main', new TreeMultiselectField('SearchTrees', 'Restrict results to these subtrees', 'Page'), 'Content'); } if (!$this->SortBy) { $this->SortBy = 'Created'; } $objFields = $this->getSelectableFields(); if ($support['SortBy']) { $sortFields = $objFields; // Remove content and groups from being sortable (as they are not relevant). unset($sortFields['Content']); unset($sortFields['Groups']); $fields->addFieldToTab('Root.Main', new DropdownField('SortBy', _t('ExtensibleSearchPage.SORT_BY', 'Sort By'), $sortFields), 'Content'); } if ($support['SortDir']) { $fields->addFieldToTab('Root.Main', new DropdownField('SortDir', _t('ExtensibleSearchPage.SORT_DIR', 'Sort Direction'), $this->dbObject('SortDir')->enumValues()), 'Content'); } $types = SiteTree::page_type_classes(); $source = array_combine($types, $types); if ($this->SearchEngine !== 'Full-Text' && $this->extension_instances) { $engine = "{$this->SearchEngine}Search"; foreach ($this->extension_instances as $instance) { if (get_class($instance) === $engine) { $instance->setOwner($this); // Trigger the following methods on the current search engine extension. if (method_exists($instance, 'updateSource')) { // add in any explicitly configured asort($source); $instance->updateSource($source); } if (method_exists($instance, 'getQueryBuilders') && $support['QueryType']) { $parsers = $instance->getQueryBuilders(); $options = array(); foreach ($parsers as $key => $objCls) { $obj = new $objCls(); $options[$key] = $obj->title; } $fields->addFieldToTab('Root.Main', new DropdownField('QueryType', _t('ExtensibleSearchPage.QUERY_TYPE', 'Query Type'), $options), 'Content'); } $instance->clearOwner(); break; } } } if ($support['SearchType']) { ksort($source); $source = array_merge($source, self::$additional_search_types); $types = new MultiValueDropdownField('SearchType', _t('ExtensibleSearchPage.SEARCH_ITEM_TYPE', 'Search items of type'), $source); $fields->addFieldToTab('Root.Main', $types, 'Content'); } if ($support['SearchOnFields']) { $fields->addFieldToTab('Root.Main', new MultiValueDropdownField('SearchOnFields', _t('ExtensibleSearchPage.INCLUDE_FIELDS', 'Search On Fields'), $objFields), 'Content'); } $boostVals = array(); for ($i = 1; $i <= 5; $i++) { $boostVals[$i] = $i; } if ($support['BoostFields']) { $fields->addFieldToTab('Root.Main', new KeyValueField('BoostFields', _t('ExtensibleSearchPage.BOOST_FIELDS', 'Boost values'), $objFields, $boostVals), 'Content'); } if ($support['BoostMatchFields']) { $fields->addFieldToTab('Root.Main', $f = new KeyValueField('BoostMatchFields', _t('ExtensibleSearchPage.BOOST_MATCH_FIELDS', 'Boost fields with field/value matches'), array(), $boostVals), 'Content'); $f->setRightTitle('Enter a field name, followed by the value to boost if found in the result set, eg "title:Home" '); } if ($support['FilterFields']) { $fields->addFieldToTab('Root.Main', $kv = new KeyValueField('FilterFields', _t('ExtensibleSearchPage.FILTER_FIELDS', 'Fields to filter by')), 'Content'); } if ($this->SearchEngine !== 'Full-Text') { $fields->addFieldToTab('Root.Main', new HeaderField('FacetHeader', _t('ExtensibleSearchPage.FACET_HEADER', 'Facet Settings')), 'Content'); } if ($support['FacetFields']) { $fields->addFieldToTab('Root.Main', new MultiValueDropdownField('FacetFields', _t('ExtensibleSearchPage.FACET_FIELDS', 'Fields to create facets for'), $objFields), 'Content'); } if ($support['CustomFacetFields']) { $fields->addFieldToTab('Root.Main', new MultiValueTextField('CustomFacetFields', _t('ExtensibleSearchPage.CUSTOM_FACET_FIELDS', 'Additional fields to create facets for')), 'Content'); } if ($support['FacetMapping']) { $facetMappingFields = $objFields; if ($this->CustomFacetFields && ($cff = $this->CustomFacetFields->getValues())) { foreach ($cff as $facetField) { $facetMappingFields[$facetField] = $facetField; } } $fields->addFieldToTab('Root.Main', new KeyValueField('FacetMapping', _t('ExtensibleSearchPage.FACET_MAPPING', 'Mapping of facet title to nice title'), $facetMappingFields), 'Content'); } if ($support['FacetQueries']) { $fields->addFieldToTab('Root.Main', new KeyValueField('FacetQueries', _t('ExtensibleSearchPage.FACET_QUERIES', 'Fields to create query facets for')), 'Content'); } if ($support['MinFacetCount']) { $fields->addFieldToTab('Root.Main', new NumericField('MinFacetCount', _t('ExtensibleSearchPage.MIN_FACET_COUNT', 'Minimum facet count for inclusion in facet results'), 2), 'Content'); } $this->extend('updateExtensibleSearchPageCMSFields', $fields); } else { $fields->addFieldToTab('Root.Main', LiteralField::create('SearchEngineNotification', "<p class='extensible-search notification'><strong>Select a Search Engine</strong></p>"), 'Title'); } // Retrieve the extensible search analytics, when enabled. if (Config::inst()->get('ExtensibleSearch', 'enable_analytics')) { // Retrieve the search analytics. $history = $this->History(); $query = new SQLQuery("Term, COUNT(*) AS Frequency, ((COUNT(*) * 100.00) / {$history->count()}) AS FrequencyPercentage, AVG(Time) AS AverageTimeTaken, (Results > 0) AS Results", 'ExtensibleSearch', "ExtensibleSearchPageID = {$this->ID}", array('Frequency' => 'DESC', 'Term' => 'ASC'), 'Term'); $analytics = ArrayList::create(); foreach ($query->execute() as $result) { $result = ArrayData::create($result); $result->FrequencyPercentage = sprintf('%.2f %%', $result->FrequencyPercentage); $result->AverageTimeTaken = sprintf('%.5f', $result->AverageTimeTaken); $result->Results = $result->Results ? 'true' : 'false'; $analytics->push($result); } // Instantiate the search analytic summary display. $fields->addFieldToTab('Root.SearchAnalytics', $summary = GridField::create('Summary', 'Summary', $analytics)->setModelClass('ExtensibleSearch')); $summaryConfiguration = $summary->getConfig(); $summaryConfiguration->removeComponentsByType('GridFieldFilterHeader'); $summaryConfiguration->addComponent($summaryExport = new GridFieldExportButton()); $summaryConfiguration->getComponentByType('GridFieldSortableHeader')->setFieldSorting(array('FrequencyPercentage' => 'Frequency')); // Update the export fields, since we're not using a data list. $summaryDisplay = array('Term' => 'Search Term', 'Frequency' => 'Frequency', 'FrequencyPercentage' => 'Frequency %', 'AverageTimeTaken' => 'Average Time Taken (s)', 'Results' => 'Has Results?'); $summaryExport->setExportColumns($summaryDisplay); // Update the summary fields. $summaryConfiguration->getComponentByType('GridFieldDataColumns')->setDisplayFields($summaryDisplay); // Instantiate the search analytic history display. $fields->addFieldToTab('Root.SearchAnalytics', $history = GridField::create('History', 'History', $history)->setModelClass('ExtensibleSearch')); $historyConfiguration = $history->getConfig(); $historyConfiguration->removeComponentsByType('GridFieldFilterHeader'); $historyConfiguration->addComponent($historyExport = new GridFieldExportButton()); // Update the custom summary fields to be sortable. $historyConfiguration->getComponentByType('GridFieldSortableHeader')->setFieldSorting(array('TimeSummary' => 'Created', 'TimeTakenSummary' => 'Time')); } // Retrieve the extensible search suggestions, when enabled. if (Config::inst()->get('ExtensibleSearchSuggestion', 'enable_suggestions')) { // Instantiate the search suggestion display. $fields->addFieldToTab('Root.SearchSuggestions', GridField::create('Suggestions', 'Suggestions', $this->Suggestions(), $suggestionsConfiguration = GridFieldConfig_RecordEditor::create())->setModelClass('ExtensibleSearchSuggestion')); $suggestionsConfiguration->removeComponentsByType('GridFieldFilterHeader'); // Update the custom summary fields to be sortable. $suggestionsConfiguration->getComponentByType('GridFieldSortableHeader')->setFieldSorting(array('FrequencySummary' => 'Frequency', 'FrequencyPercentage' => 'Frequency', 'ApprovedField' => 'Approved')); } return $fields; }