/**
  *	The process to automatically construct data object output configurations, executed on project build.
  */
 public function requireDefaultRecords()
 {
     parent::requireDefaultRecords();
     // Grab the list of data objects that have been completely removed.
     foreach (DB::getConn()->tableList() as $table) {
         // Delete existing output configurations for these data objects.
         if (!class_exists($table)) {
             $existing = DataObjectOutputConfiguration::get_one('DataObjectOutputConfiguration', "IsFor = '" . Convert::raw2sql($table) . "'");
             $this->deleteConfiguration($table, $existing);
         }
     }
     // Grab the list of all data object types, along with any inclusions/exclusions defined.
     $objects = ClassInfo::subclassesFor('DataObject');
     $inclusions = self::$custom_inclusions;
     $exclusions = array_unique(array_merge(self::$exclusions, self::$custom_exclusions));
     // Check existing output configurations for these data objects.
     foreach ($objects as $object) {
         $existing = DataObjectOutputConfiguration::get_one('DataObjectOutputConfiguration', "IsFor = '" . Convert::raw2sql($object) . "'");
         // Delete existing output configurations for invalid data objects, or for those excluded.
         if ($existing && (self::$disabled || get_parent_class($object) !== 'DataObject' || ClassInfo::classImplements($object, 'TestOnly') || count($inclusions) > 0 && !in_array($object, $inclusions) || count($inclusions) === 0 && in_array($object, $exclusions))) {
             $this->deleteConfiguration($object, $existing);
         } else {
             if (!$existing && !self::$disabled && get_parent_class($object) === 'DataObject' && !ClassInfo::classImplements($object, 'TestOnly') && (count($inclusions) > 0 && in_array($object, $inclusions) || count($inclusions) === 0 && !in_array($object, $exclusions))) {
                 $this->addConfiguration($object);
             }
         }
     }
 }
예제 #2
0
 /**
  *	Determine the existing and configuration defined tag types to consolidate.
  *
  *	@return array(string, string)
  */
 public function getFusionTagTypes()
 {
     // Determine existing tag types.
     $types = array();
     $configuration = Config::inst();
     // The tag type exclusions need checking.
     $exclusions = $configuration->get('FusionService', 'tag_type_exclusions');
     $classes = ClassInfo::subclassesFor('DataObject');
     unset($classes['FusionTag']);
     foreach ($classes as $class) {
         // Determine the tag types to consolidate, based on data objects ending with "Tag".
         if (strpos(strrev($class), strrev('Tag')) === 0 && !in_array($class, $exclusions) && !ClassInfo::classImplements($class, 'TestOnly')) {
             // Use the title field as a default.
             $types[$class] = 'Title';
         }
     }
     // Determine configuration defined tag types.
     foreach ($configuration->get('FusionService', 'custom_tag_types') as $type => $field) {
         if (in_array($type, $classes) && !in_array($type, $exclusions)) {
             // Use the configuration defined field.
             $types[$type] = $field;
         }
     }
     return $types;
 }
 /**
  * Sets the renderer for markdown fields to use
  * @param {string} $renderer Class Name of an implementation of IMarkdownRenderer
  */
 public static function setRenderer($renderer)
 {
     if (ClassInfo::classImplements($renderer, 'IMarkdownRenderer')) {
         self::$renderer = $renderer;
     } else {
         user_error('The renderer ' . $renderer . ' does not implement IMarkdownRenderer', E_USER_ERROR);
     }
 }
 public static function get_question_types()
 {
     $classes = array();
     foreach (ClassInfo::subclassesFor('Question') as $i => $class) {
         if ($class != 'Question' && !ClassInfo::classImplements($class, 'TestOnly')) {
             $classes[$class] = $class;
         }
     }
     return $classes;
 }
 /**
  * Returns a filtered list of fields which could contain shortcodes.
  *
  * @param String
  * @return Array Map of class names to an array of field names on these classes.
  */
 function getShortcodeFields($class)
 {
     $fields = array();
     $ancestry = array_values(ClassInfo::dataClassesFor($class));
     foreach ($ancestry as $ancestor) {
         if (ClassInfo::classImplements($ancestor, 'TestOnly')) {
             continue;
         }
         $ancFields = DataObject::custom_database_fields($ancestor);
         if ($ancFields) {
             foreach ($ancFields as $ancFieldName => $ancFieldSpec) {
                 if (preg_match($this->fieldSpecRegex, $ancFieldSpec)) {
                     if (!@$fields[$ancestor]) {
                         $fields[$ancestor] = array();
                     }
                     $fields[$ancestor][$ancFieldName] = $ancFieldSpec;
                 }
             }
         }
     }
     return $fields;
 }
 private static function cache_composite_fields($class)
 {
     $compositeFields = array();
     $fields = Config::inst()->get($class, 'db', Config::UNINHERITED);
     if ($fields) {
         foreach ($fields as $fieldName => $fieldClass) {
             if (!is_string($fieldClass)) {
                 continue;
             }
             // Strip off any parameters
             $bPos = strpos('(', $fieldClass);
             if ($bPos !== FALSE) {
                 $fieldClass = substr(0, $bPos, $fieldClass);
             }
             // Test to see if it implements CompositeDBField
             if (ClassInfo::classImplements($fieldClass, 'CompositeDBField')) {
                 $compositeFields[$fieldName] = $fieldClass;
             }
         }
     }
     ExternalDataObject::$_cache_composite_fields[$class] = $compositeFields;
 }
 public function getCMSFields()
 {
     if ($this->List) {
         $opts = array('random' => 'A random list of objects', 'query' => 'A specific list of objects');
     } else {
         $opts = array('static' => 'A static value', 'random' => 'A random object', 'query' => 'A specific object');
     }
     $map = ArrayLib::valuekey(ClassInfo::subclassesFor('DataObject'));
     unset($map['DataObject']);
     foreach ($map as $k => $class) {
         if (ClassInfo::classImplements($class, 'TestOnly')) {
             unset($map[$class]);
         }
     }
     ksort($map);
     $f = FieldList::create(TabSet::create('Root'));
     $f->addFieldToTab('Root.Main', ReadonlyField::create('Variable', 'Variable name'));
     $f->addFieldToTab('Root.Main', OptionsetField::create('ValueType', 'Value type', $opts));
     $f->addFieldToTab('Root.Main', DropdownField::create('RecordClass', 'Object type', $map)->displayIf('ValueType')->isEqualTo('random')->orIf('ValueType')->isEqualTo('query')->end());
     $f->addFieldToTab('Root.Main', TextField::create('Value')->displayIf('ValueType')->isEqualTo('static')->end());
     $f->addFieldToTab('Root.Main', TextField::create('Query', 'Query string')->displayIf('ValueType')->isEqualTo('query')->end()->setDescription('E.g. Name:StartsWith=Uncle&Status=Awesome'));
     return $f;
 }
예제 #8
0
	/**
	 * Build a {@link SQLQuery} object to perform the given query.
	 *
	 * @param string $filter A filter to be inserted into the WHERE clause.
	 * @param string|array $sort A sort expression to be inserted into the ORDER BY clause. If omitted, self::$default_sort will be used.
	 * @param string|array $limit A limit expression to be inserted into the LIMIT clause.
	 * @param string $join A single join clause. This can be used for filtering, only 1 instance of each DataObject will be returned.
	 * @param boolean $restictClasses Restrict results to only objects of either this class of a subclass of this class
	 * @param string $having A filter to be inserted into the HAVING clause.
	 *
	 * @return SQLQuery Query built.
	 */
	public function buildSQL($filter = "", $sort = "", $limit = "", $join = "", $restrictClasses = true, $having = "") {
		// Find a default sort
		if(!$sort) {
			$sort = $this->stat('default_sort');
		}

		// Get the tables to join to
		$tableClasses = ClassInfo::dataClassesFor($this->class);
		if(!$tableClasses) {
			if(!ManifestBuilder::has_been_included()) {
				user_error("DataObjects have been requested before the manifest is loaded. Please ensure you are not querying the database in _config.php.", E_USER_ERROR);
			} else {
				user_error("DataObject::buildSQL: Can't find data classes (classes linked to tables) for $this->class. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR);
			}
		}

		$baseClass = array_shift($tableClasses);
		$select = array("`$baseClass`.*");

		// Build our intial query
		$query = new SQLQuery($select);
		$query->from("`$baseClass`");
		$query->where($filter);
		$query->orderby($sort);
		$query->limit($limit);

		// Add SQL for multi-value fields on the base table
		$databaseFields = $this->databaseFields();
		if($databaseFields) foreach($databaseFields as $k => $v) {
			if(!in_array($k, array('ClassName', 'LastEdited', 'Created'))) {
				if(ClassInfo::classImplements($v, 'CompositeDBField')) {
					$this->dbObject($k)->addToQuery($query);
				}
			}
		}
		// Join all the tables
		if($tableClasses && self::$subclass_access) {
			foreach($tableClasses as $tableClass) {
				$query->from[$tableClass] = "LEFT JOIN `$tableClass` ON `$tableClass`.ID = `$baseClass`.ID";
				$query->select[] = "`$tableClass`.*";

				// Add SQL for multi-value fields
				$SNG = singleton($tableClass);
				$databaseFields = $SNG->databaseFields();
				if($databaseFields) foreach($databaseFields as $k => $v) {
					if(!in_array($k, array('ClassName', 'LastEdited', 'Created'))) {
						if(ClassInfo::classImplements($v, 'CompositeDBField')) {
							$SNG->dbObject($k)->addToQuery($query);
						}
					}
				}
			}
		}

		$query->select[] = "`$baseClass`.ID";
		$query->select[] = "if(`$baseClass`.ClassName,`$baseClass`.ClassName,'$baseClass') AS RecordClassName";

		// Get the ClassName values to filter to
		$classNames = ClassInfo::subclassesFor($this->class);

		if(!$classNames) {
			user_error("DataObject::get() Can't find data sub-classes for '$callerClass'");
		}

		// If querying the base class, don't bother filtering on class name
		if($restrictClasses && $this->class != $baseClass) {
			// Get the ClassName values to filter to
			$classNames = ClassInfo::subclassesFor($this->class);
			if(!$classNames) {
				user_error("DataObject::get() Can't find data sub-classes for '$callerClass'");
			}

			$query->where[] = "`$baseClass`.ClassName IN ('" . implode("','", $classNames) . "')";
		}

		if($having) {
			$query->having[] = $having;
		}

		if($join) {
			$query->from[] = $join;
			$query->groupby[] = reset($query->from) . ".ID";
		}

		return $query;
	}
예제 #9
0
 function providePermissions()
 {
     $perms = array("CMS_ACCESS_LeftAndMain" => array('name' => _t('CMSMain.ACCESSALLINTERFACES', 'Access to all CMS sections'), 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'), 'help' => _t('CMSMain.ACCESSALLINTERFACESHELP', 'Overrules more specific access settings.'), 'sort' => -100));
     // Add any custom ModelAdmin subclasses. Can't put this on ModelAdmin itself
     // since its marked abstract, and needs to be singleton instanciated.
     foreach (ClassInfo::subclassesFor('ModelAdmin') as $i => $class) {
         if ($class == 'ModelAdmin') {
             continue;
         }
         if (ClassInfo::classImplements($class, 'TestOnly')) {
             continue;
         }
         $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title_for_class($class));
         $perms["CMS_ACCESS_" . $class] = array('name' => _t('CMSMain.ACCESS', "Access to '{title}' section", "Item in permission selection identifying the admin section. Example: Access to 'Files & Images'", array('title' => $title)), 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'));
     }
     return $perms;
 }
 /**
  * Gets the rendered results from searching
  * @return {HTMLText}
  */
 public function getSearchResults()
 {
     if ($this->config()->search_engine === false || !class_exists($this->config()->search_engine) || !ClassInfo::classImplements($this->config()->search_engine, 'ICMSUserDocsSearchEngine')) {
         return $this->httpError(404);
     }
     $results = Injector::inst()->get($this->config()->search_engine)->getSearchResults($this->request->getVar('q'), $this->request->getVar('start'), $this->request);
     return $results->renderWith('CMSDocumentationViewer_results');
 }
예제 #11
0
파일: CMSMenu.php 프로젝트: rixrix/sapphire
 /**
  * A utility funciton to retrieve subclasses of a given class that
  * are instantiable (ie, not abstract) and have a valid menu title.
  *
  * @todo A variation of this function could probably be moved to {@link ClassInfo}
  * @param string $root The root class to begin finding subclasses
  * @param boolean $recursive Look for subclasses recursively?
  * @return array Valid, unique subclasses
  */
 public static function get_cms_classes($root = 'LeftAndMain', $recursive = true)
 {
     $subClasses = array_values(ClassInfo::subclassesFor($root));
     foreach ($subClasses as $className) {
         if ($recursive && $className != $root) {
             $subClasses = array_merge($subClasses, array_values(ClassInfo::subclassesFor($className)));
         }
     }
     $subClasses = array_unique($subClasses);
     foreach ($subClasses as $key => $className) {
         // Remove abstract classes and LeftAndMain
         $classReflection = new ReflectionClass($className);
         if (!$classReflection->isInstantiable() || 'LeftAndMain' == $className || ClassInfo::classImplements($className, 'TestOnly')) {
             unset($subClasses[$key]);
         }
     }
     return $subClasses;
 }
 /**
  * Build a {@link SQLQuery} object to perform the given query.
  *
  * @param string $filter A filter to be inserted into the WHERE clause.
  * @param string|array $sort A sort expression to be inserted into the ORDER BY clause. If omitted, self::$default_sort will be used.
  * @param string|array $limit A limit expression to be inserted into the LIMIT clause.
  * @param string $join A single join clause. This can be used for filtering, only 1 instance of each DataObject will be returned.
  * @param boolean $restictClasses Restrict results to only objects of either this class of a subclass of this class
  * @param string $having A filter to be inserted into the HAVING clause.
  *
  * @return SQLQuery Query built.
  */
 public function buildSQL($filter = "", $sort = "", $limit = "", $join = "", $restrictClasses = true, $having = "")
 {
     // Cache the big hairy part of buildSQL
     if (!isset(self::$cache_buildSQL_query[$this->class])) {
         // Get the tables to join to
         $tableClasses = ClassInfo::dataClassesFor($this->class);
         if (!$tableClasses) {
             if (!ManifestBuilder::has_been_included()) {
                 user_error("DataObjects have been requested before the manifest is loaded. Please ensure you are not querying the database in _config.php.", E_USER_ERROR);
             } else {
                 user_error("DataObject::buildSQL: Can't find data classes (classes linked to tables) for {$this->class}. Please ensure you run dev/build after creating a new DataObject.", E_USER_ERROR);
             }
         }
         $baseClass = array_shift($tableClasses);
         // $collidingFields will keep a list fields that appear in mulitple places in the class
         // heirarchy for this table.  They will be dealt with more explicitly in the SQL query
         // to ensure that junk data from other tables doesn't corrupt data objects
         $collidingFields = array();
         // Build our intial query
         $query = new SQLQuery(array());
         $query->from("\"{$baseClass}\"");
         // Add SQL for multi-value fields on the base table
         $databaseFields = self::database_fields($baseClass);
         if ($databaseFields) {
             foreach ($databaseFields as $k => $v) {
                 if (!in_array($k, array('ClassName', 'LastEdited', 'Created')) && ClassInfo::classImplements($v, 'CompositeDBField')) {
                     $this->dbObject($k)->addToQuery($query);
                 } else {
                     $query->select[$k] = "\"{$baseClass}\".\"{$k}\"";
                 }
             }
         }
         // Join all the tables
         if ($tableClasses && self::$subclass_access) {
             foreach ($tableClasses as $tableClass) {
                 $query->from[$tableClass] = "LEFT JOIN \"{$tableClass}\" ON \"{$tableClass}\".\"ID\" = \"{$baseClass}\".\"ID\"";
                 // Add SQL for multi-value fields
                 $databaseFields = self::database_fields($tableClass);
                 $compositeFields = self::composite_fields($tableClass, false);
                 if ($databaseFields) {
                     foreach ($databaseFields as $k => $v) {
                         if (!isset($compositeFields[$k])) {
                             // Update $collidingFields if necessary
                             if (isset($query->select[$k])) {
                                 if (!isset($collidingFields[$k])) {
                                     $collidingFields[$k] = array($query->select[$k]);
                                 }
                                 $collidingFields[$k][] = "\"{$tableClass}\".\"{$k}\"";
                             } else {
                                 $query->select[$k] = "\"{$tableClass}\".\"{$k}\"";
                             }
                         }
                     }
                 }
                 if ($compositeFields) {
                     foreach ($compositeFields as $k => $v) {
                         $dbO = $this->dbObject($k);
                         if ($dbO) {
                             $dbO->addToQuery($query);
                         }
                     }
                 }
             }
         }
         // Resolve colliding fields
         if ($collidingFields) {
             foreach ($collidingFields as $k => $collisions) {
                 $caseClauses = array();
                 foreach ($collisions as $collision) {
                     if (preg_match('/^"([^"]+)"/', $collision, $matches)) {
                         $collisionBase = $matches[1];
                         $collisionClasses = ClassInfo::subclassesFor($collisionBase);
                         $caseClauses[] = "WHEN \"{$baseClass}\".\"ClassName\" IN ('" . implode("', '", $collisionClasses) . "') THEN {$collision}";
                     } else {
                         user_error("Bad collision item '{$collision}'", E_USER_WARNING);
                     }
                 }
                 $query->select[$k] = "CASE " . implode(" ", $caseClauses) . " ELSE NULL END" . " AS \"{$k}\"";
             }
         }
         $query->select[] = "\"{$baseClass}\".\"ID\"";
         $query->select[] = "CASE WHEN \"{$baseClass}\".\"ClassName\" IS NOT NULL THEN \"{$baseClass}\".\"ClassName\" ELSE '{$baseClass}' END AS \"RecordClassName\"";
         // Get the ClassName values to filter to
         $classNames = ClassInfo::subclassesFor($this->class);
         if (!$classNames) {
             user_error("DataObject::get() Can't find data sub-classes for '{$callerClass}'");
         }
         // If querying the base class, don't bother filtering on class name
         if ($restrictClasses && $this->class != $baseClass) {
             // Get the ClassName values to filter to
             $classNames = ClassInfo::subclassesFor($this->class);
             if (!$classNames) {
                 user_error("DataObject::get() Can't find data sub-classes for '{$callerClass}'");
             }
             $query->where[] = "\"{$baseClass}\".\"ClassName\" IN ('" . implode("','", $classNames) . "')";
         }
         self::$cache_buildSQL_query[$this->class] = clone $query;
     } else {
         $query = clone self::$cache_buildSQL_query[$this->class];
     }
     // Find a default sort
     if (!$sort) {
         $sort = $this->stat('default_sort');
     }
     // Add quoting to sort expression if it's a simple column name
     if (preg_match('/^[A-Z][A-Z0-9_]*$/i', $sort)) {
         $sort = "\"{$sort}\"";
     }
     $query->where($filter);
     $query->orderby($sort);
     $query->limit($limit);
     if ($having) {
         $query->having[] = $having;
     }
     if ($join) {
         $query->from[] = $join;
         // In order to group by unique columns we have to group by everything listed in the select
         foreach ($query->select as $field) {
             // Skip the _SortColumns; these are only going to be aggregate functions
             if (preg_match('/AS\\s+\\"?_SortColumn/', $field, $matches)) {
                 // Identify columns with aliases, and ignore the alias.  Making use of the alias in
                 // group by was causing problems when those queries were subsequently passed into
                 // SQLQuery::unlimitedRowCount.
             } else {
                 if (preg_match('/^(.*)\\s+AS\\s+(\\"[^"]+\\")\\s*$/', $field, $matches)) {
                     $query->groupby[] = $matches[1];
                     // Otherwise just use the field as is
                 } else {
                     $query->groupby[] = $field;
                 }
             }
         }
     }
     return $query;
 }
예제 #13
0
 /**
  * A utility funciton to retrieve subclasses of a given class that
  * are instantiable (ie, not abstract) and have a valid menu title.
  *
  * Sorted by url_priority config.
  *
  * @todo A variation of this function could probably be moved to {@link ClassInfo}
  * @param string $root The root class to begin finding subclasses
  * @param boolean $recursive Look for subclasses recursively?
  * @param string $sort Name of config on which to sort. Can be 'menu_priority' or 'url_priority'
  * @return array Valid, unique subclasses
  */
 public static function get_cms_classes($root = null, $recursive = true, $sort = self::MENU_PRIORITY)
 {
     if (!$root) {
         $root = 'LeftAndMain';
     }
     /** @todo Make these actual abstract classes */
     $abstractClasses = ['LeftAndMain', 'SilverStripe\\CMS\\Controllers\\CMSMain'];
     $subClasses = array_values(ClassInfo::subclassesFor($root));
     foreach ($subClasses as $className) {
         if ($recursive && $className != $root) {
             $subClasses = array_merge($subClasses, array_values(ClassInfo::subclassesFor($className)));
         }
     }
     $subClasses = array_unique($subClasses);
     foreach ($subClasses as $key => $className) {
         // Remove abstract classes and LeftAndMain
         if (in_array($className, $abstractClasses) || ClassInfo::classImplements($className, 'TestOnly')) {
             unset($subClasses[$key]);
         } else {
             // Separate conditional to avoid autoloading the class
             $classReflection = new ReflectionClass($className);
             if (!$classReflection->isInstantiable()) {
                 unset($subClasses[$key]);
             }
         }
     }
     // Sort by specified sorting config
     usort($subClasses, function ($a, $b) use($sort) {
         $priorityA = Config::inst()->get($a, $sort);
         $priorityB = Config::inst()->get($b, $sort);
         return $priorityB - $priorityA;
     });
     return $subClasses;
 }
예제 #14
0
 /**
  * Internal cacher for the composite field information
  */
 private static function cache_composite_fields($class)
 {
     $compositeFields = array();
     $fields = Object::uninherited_static($class, 'db');
     if ($fields) {
         foreach ($fields as $fieldName => $fieldClass) {
             // Strip off any parameters
             $bPos = strpos('(', $fieldClass);
             if ($bPos !== FALSE) {
                 $fieldClass = substr(0, $bPos, $fieldClass);
             }
             // Test to see if it implements CompositeDBField
             if (ClassInfo::classImplements($fieldClass, 'CompositeDBField')) {
                 $compositeFields[$fieldName] = $fieldClass;
             }
         }
     }
     self::$_cache_composite_fields[$class] = $compositeFields;
 }
 /**
  * @return array
  */
 public function providePermissions()
 {
     $perms = array();
     // Add any custom SinglePageAdmin subclasses.
     foreach (ClassInfo::subclassesFor('SinglePageAdmin') as $i => $class) {
         if ($class == 'SinglePageAdmin') {
             continue;
         }
         if (ClassInfo::classImplements($class, 'TestOnly')) {
             continue;
         }
         $title = _t("{$class}.MENUTITLE", LeftAndMain::menu_title_for_class($class));
         $perms["CMS_ACCESS_" . $class] = array('name' => _t('CMSMain.ACCESS', "Access to '{title}' section", "Item in permission selection identifying the admin section. Example: Access to 'Files & Images'", array('title' => $title)), 'category' => _t('Permission.CMS_ACCESS_CATEGORY', 'CMS Access'));
     }
     return $perms;
 }
 public function testGetSerializer()
 {
     $serializer = CacheHelper::get_serializer();
     $this->assertTrue(ClassInfo::classImplements($serializer->class, 'ICacheSerializer'));
 }
 public static function get_extra_config($class, $extension, $args)
 {
     if (!ClassInfo::classImplements($class, "ContentNotifier")) {
         throw new RuntimeException("{$class} must implement ContentNotifier to be used by the ContentNotifierExtension");
     }
 }
 /**
  * Get config store
  * 
  * @return SolrConfigStore
  */
 protected function getSolrConfigStore()
 {
     $options = Solr::solr_options();
     if (!isset($options['indexstore']) || !($indexstore = $options['indexstore'])) {
         user_error('No index configuration for Solr provided', E_USER_ERROR);
     }
     // Find the IndexStore handler, which will handle uploading config files to Solr
     $mode = $indexstore['mode'];
     if ($mode == 'file') {
         return new SolrConfigStore_File($indexstore);
     } elseif ($mode == 'webdav') {
         return new SolrConfigStore_WebDAV($indexstore);
     } elseif (ClassInfo::exists($mode) && ClassInfo::classImplements($mode, 'SolrConfigStore')) {
         return new $mode($indexstore);
     } else {
         user_error('Unknown Solr index mode ' . $indexstore['mode'], E_USER_ERROR);
     }
 }