public function __construct($parent, $name, $title = null, $options = null)
 {
     parent::__construct($parent, $name, $title, $options);
     list($parentClass, $componentClass, $parentField, $componentField, $table) = $parent->many_many($this->name);
     $this->parentField = $parentField;
     $this->componentField = $componentField;
     $this->joinTable = $table;
     $this->otherClass = $parent->class == $parentClass || ClassInfo::is_subclass_of($parent->class, $parentClass) ? $componentClass : $parentClass;
 }
예제 #2
0
 /**
  *
  * @param string $dataPresenterClassName 
  * @throws Exception
  */
 function setDataPresenter($dataPresenterClassName)
 {
     if (!$dataPresenterClassName) {
         throw new Exception('Datapresenter for Datagrid must be set with a class');
     }
     if (!class_exists($dataPresenterClassName)) {
         throw new Exception('Datapresenter for Datagrid must be set with an existing class');
     }
     if ($dataPresenterClassName != 'DatagridPresenter' && !ClassInfo::is_subclass_of($dataPresenterClassName, 'DatagridPresenter')) {
         throw new Exception('Datapresenter "$dataPresenterClassName" must inherit DatagridPresenter');
     }
     $this->dataPresenterClassName = $dataPresenterClassName;
     return $this;
 }
 public function __construct(DataObject $controller, $name, $title = null, $className = null, $source = array(), $addTitle = null, $defaultsProperties = array(), $form = null)
 {
     $hasOne = false;
     if (!$title) {
         $this->title = self::name_to_label($name);
     }
     if (!$className) {
         if (substr($name, -2) == 'ID') {
             $name = substr($name, 0, -2);
         }
         if (!($hasOne = $className = $controller->has_one($name)) && !($className = $controller->belongs_to($name)) && (($settings = $controller->has_many($name)) || ($settings = $controller->many_many($name)))) {
             if (is_array($settings)) {
                 $className = $settings[1];
             } else {
                 $className = $settings;
             }
             $this->fieldType = 'CheckboxSetField';
         }
         if (!$className) {
             trigger_error('Couldn\'t determine class type from field name "' . $name . '". Please define the class name.');
         }
         if ($hasOne) {
             $name .= 'ID';
         }
     } else {
         if ($rels = $controller->has_many() + $controller->many_many()) {
             foreach ($rels as $rel => $class) {
                 if ($class == $className || ClassInfo::is_subclass_of($class, $className)) {
                     $this->fieldType = 'CheckboxSetField';
                     break;
                 }
             }
         }
     }
     if (!class_exists($className)) {
         trigger_error($className . ' class doesn\'t exist');
     }
     $this->setDefaults($defaultsProperties);
     $this->className = $className;
     $this->controller = $controller;
     parent::__construct($name, $title, $source, null, $form);
 }
예제 #4
0
파일: File.php 프로젝트: rixrix/sapphire
 /**
  * See {@link get_class_for_file_extension()}.
  * 
  * @param String|array
  * @param String
  */
 static function set_class_for_file_extension($exts, $class)
 {
     if (!is_array($exts)) {
         $exts = array($exts);
     }
     foreach ($exts as $ext) {
         if (ClassInfo::is_subclass_of($ext, 'File')) {
             throw new InvalidArgumentException(sprintf('Class "%s" (for extension "%s") is not a valid subclass of File', $class, $ext));
         }
         self::$class_for_file_extension[$ext] = $class;
     }
 }
예제 #5
0
 /**
  * Determine if a table is supporting the Versioned extensions (e.g. $table_versions does exists)
  *
  * @param string $table Table name
  * @return boolean
  */
 function canBeVersioned($table)
 {
     return ClassInfo::exists($table) && ClassInfo::is_subclass_of($table, 'DataObject') && DataObject::has_own_table($table);
 }
 /**
  * Return true if this dynamic template can be applied to a specified class.
  * @param  $class
  * @return bool
  */
 public function appliesToClass($class)
 {
     if (!isset($this->metadata)) {
         return true;
     }
     // no metadata so no class constraints
     if (!isset($this->metadata["classes"]) || count($this->metadata["classes"]) == 0) {
         return true;
     }
     // Check each item in classes. Each will be the name of a base class. If
     // the class of the item passed in is a subclass, this template applies
     // to it.
     foreach ($this->metadata["classes"] as $classConstraint) {
         if (ClassInfo::is_subclass_of($class, $classConstraint)) {
             return true;
         }
     }
     return false;
 }
 /**
  * Handles widgets attached to a page through one or more {@link WidgetArea} elements.
  * Iterated through each $has_one relation with a {@link WidgetArea}
  * and looks for connected widgets by their database identifier.
  * Assumes URLs in the following format: <URLSegment>/widget/<Widget-ID>.
  * 
  * @return RequestHandler
  */
 function handleWidget()
 {
     $SQL_id = $this->request->param('ID');
     if (!$SQL_id) {
         return false;
     }
     // find WidgetArea relations
     $widgetAreaRelations = array();
     $hasOnes = $this->dataRecord->has_one();
     if (!$hasOnes) {
         return false;
     }
     foreach ($hasOnes as $hasOneName => $hasOneClass) {
         if ($hasOneClass == 'WidgetArea' || ClassInfo::is_subclass_of($hasOneClass, 'WidgetArea')) {
             $widgetAreaRelations[] = $hasOneName;
         }
     }
     // find widget
     $widget = null;
     foreach ($widgetAreaRelations as $widgetAreaRelation) {
         if ($widget) {
             break;
         }
         $widget = $this->dataRecord->{$widgetAreaRelation}()->Widgets(sprintf('"Widget"."ID" = %d', $SQL_id))->First();
     }
     if (!$widget) {
         user_error('No widget found', E_USER_ERROR);
     }
     // find controller
     $controllerClass = '';
     foreach (array_reverse(ClassInfo::ancestry($widget->class)) as $widgetClass) {
         $controllerClass = "{$widgetClass}_Controller";
         if (class_exists($controllerClass)) {
             break;
         }
     }
     if (!$controllerClass) {
         user_error(sprintf('No controller available for %s', $widget->class), E_USER_ERROR);
     }
     return new $controllerClass($widget);
 }
 /**
  * Add an extension to a specific class.
  * As an alternative, extensions can be added to a specific class
  * directly in the {@link Object::$extensions} array.
  * See {@link SiteTree::$extensions} for examples.
  * Keep in mind that the extension will only be applied to new
  * instances, not existing ones (including all instances created through {@link singleton()}).
  *
  * @param string $class Class that should be decorated - has to be a subclass of {@link Object}
  * @param string $extension Subclass of {@link Extension} with optional parameters 
  *  as a string, e.g. "Versioned" or "Translatable('Param')"
  */
 public static function add_extension($class, $extension)
 {
     if (!preg_match('/^([^(]*)/', $extension, $matches)) {
         return false;
     }
     $extensionClass = $matches[1];
     if (!class_exists($extensionClass)) {
         user_error(sprintf('Object::add_extension() - Can\'t find extension class for "%s"', $extensionClass), E_USER_ERROR);
     }
     if (!ClassInfo::is_subclass_of($extensionClass, 'Extension')) {
         user_error(sprintf('Object::add_extension() - Extension "%s" is not a subclass of Extension', $extensionClass), E_USER_ERROR);
     }
     // unset some caches
     self::$cached_statics[$class]['extensions'] = null;
     $subclasses = ClassInfo::subclassesFor($class);
     $subclasses[] = $class;
     if ($subclasses) {
         foreach ($subclasses as $subclass) {
             unset(self::$classes_constructed[$subclass]);
             unset(self::$extra_methods[$subclass]);
         }
     }
     // merge with existing static vars
     $extensions = self::uninherited_static($class, 'extensions');
     // We use unshift rather than push so that module extensions are added before built-in ones.
     // in particular, this ensures that the Versioned rewriting is done last.
     if ($extensions) {
         array_unshift($extensions, $extension);
     } else {
         $extensions = array($extension);
     }
     self::set_static($class, 'extensions', $extensions);
     // load statics now for DataObject classes
     if (ClassInfo::is_subclass_of($class, 'DataObject')) {
         DataObjectDecorator::load_extra_statics($class, $extension);
     }
 }
예제 #9
0
파일: Object.php 프로젝트: rixrix/sapphire
 /**
  * Remove an extension from a class.
  * Keep in mind that this won't revert any datamodel additions
  * of the extension at runtime, unless its used before the
  * schema building kicks in (in your _config.php).
  * Doesn't remove the extension from any {@link Object}
  * instances which are already created, but will have an
  * effect on new extensions.
  * Clears any previously created singletons through {@link singleton()}
  * to avoid side-effects from stale extension information.
  * 
  * @todo Add support for removing extensions with parameters
  *
  * @param string $class
  * @param string $extension Classname of an {@link Extension} subclass, without parameters
  */
 public static function remove_extension($class, $extension)
 {
     // unload statics now for DataObject classes
     if (ClassInfo::is_subclass_of($class, 'DataObject')) {
         if (!preg_match('/^([^(]*)/', $extension, $matches)) {
             user_error("Bad extension '{$extension}'", E_USER_WARNING);
         } else {
             $extensionClass = $matches[1];
             DataObjectDecorator::unload_extra_statics($class, $extensionClass);
         }
     }
     if (self::has_extension($class, $extension)) {
         self::set_static($class, 'extensions', array_diff(self::uninherited_static($class, 'extensions'), array($extension)));
     }
     // unset singletons to avoid side-effects
     global $_SINGLETONS;
     $_SINGLETONS = array();
     // unset some caches
     self::$cached_statics[$class]['extensions'] = null;
     $subclasses = ClassInfo::subclassesFor($class);
     $subclasses[] = $class;
     if ($subclasses) {
         foreach ($subclasses as $subclass) {
             unset(self::$classes_constructed[$subclass]);
             unset(self::$extra_methods[$subclass]);
         }
     }
 }
 /**
  * Matches a URL pattern
  * The pattern can contain a number of segments, separated by / (and an extension indicated by a .)
  * 
  * The parts can be either literals, or, if they start with a $ they are interpreted as variables.
  *  - Literals must be provided in order to match
  *  - $Variables are optional
  *  - However, if you put ! at the end of a variable, then it becomes mandatory.
  * 
  * For example:
  *  - admin/crm/list will match admin/crm/$Action/$ID/$OtherID, but it won't match admin/crm/$Action!/$ClassName!
  * 
  * The pattern can optionally start with an HTTP method and a space.  For example, "POST $Controller/$Action".
  * This is used to define a rule that only matches on a specific HTTP method.
  */
 function match($pattern, $shiftOnSuccess = false)
 {
     // Check if a specific method is required
     if (preg_match('/^([A-Za-z]+) +(.*)$/', $pattern, $matches)) {
         $requiredMethod = $matches[1];
         if ($requiredMethod != $this->httpMethod) {
             return false;
         }
         // If we get this far, we can match the URL pattern as usual.
         $pattern = $matches[2];
     }
     // Special case for the root URL controller
     if (!$pattern) {
         return $this->dirParts == array() ? array('Matched' => true) : false;
     }
     // Check for the '//' marker that represents the "shifting point"
     $doubleSlashPoint = strpos($pattern, '//');
     if ($doubleSlashPoint !== false) {
         $shiftCount = substr_count(substr($pattern, 0, $doubleSlashPoint), '/') + 1;
         $pattern = str_replace('//', '/', $pattern);
         $patternParts = explode('/', $pattern);
     } else {
         $patternParts = explode('/', $pattern);
         $shiftCount = sizeof($patternParts);
     }
     $matched = true;
     $arguments = array();
     foreach ($patternParts as $i => $part) {
         $part = trim($part);
         // Match a variable
         if (isset($part[0]) && $part[0] == '$') {
             // A variable ending in ! is required
             if (substr($part, -1) == '!') {
                 $varRequired = true;
                 $varName = substr($part, 1, -1);
             } else {
                 $varRequired = false;
                 $varName = substr($part, 1);
             }
             // Fail if a required variable isn't populated
             if ($varRequired && !isset($this->dirParts[$i])) {
                 return false;
             }
             $arguments[$varName] = isset($this->dirParts[$i]) ? $this->dirParts[$i] : null;
             if ($part == '$Controller' && (!ClassInfo::exists($arguments['Controller']) || !ClassInfo::is_subclass_of($arguments['Controller'], 'Controller'))) {
                 return false;
             }
             // Literal parts with extension
         } else {
             if (isset($this->dirParts[$i]) && $this->dirParts[$i] . '.' . $this->extension == $part) {
                 continue;
                 // Literal parts must always be there
             } else {
                 if (!isset($this->dirParts[$i]) || $this->dirParts[$i] != $part) {
                     return false;
                 }
             }
         }
     }
     if ($shiftOnSuccess) {
         $this->shift($shiftCount);
         // We keep track of pattern parts that we looked at but didn't shift off.
         // This lets us say that we have *parsed* the whole URL even when we haven't *shifted* it all
         $this->unshiftedButParsedParts = sizeof($patternParts) - $shiftCount;
     }
     $this->latestParams = $arguments;
     // Load the arguments that actually have a value into $this->allParams
     // This ensures that previous values aren't overridden with blanks
     foreach ($arguments as $k => $v) {
         if ($v || !isset($this->allParams[$k])) {
             $this->allParams[$k] = $v;
         }
     }
     if ($arguments === array()) {
         $arguments['_matched'] = true;
     }
     return $arguments;
 }
 function getReturnedTypes()
 {
     $classes = array();
     if ($this->noun == 'RESTRoot') {
         $classes = RESTRoot::get_registered();
     } else {
         foreach ($this->methodBlocks as $name => $block) {
             $return = $block['return']['details'];
             $words = explode(' ', $return);
             $type = count($words) ? $words[0] : '';
             $name = preg_replace('/^get([A-Z])/', '$1', $name);
             if ($name == 'Items') {
                 $name = "{id}";
             }
             $type = preg_replace('/^\\[([^\\]]+)\\]$/', '$1', $type);
             if ($type && ClassInfo::is_subclass_of($type, 'RESTNoun')) {
                 $classes[$name] = $type;
             }
         }
     }
     // Build a new class inspector for each
     $res = new ArrayList();
     foreach ($classes as $func => $class) {
         $inspect = new RESTDocGenerator_NestingInspector($class, $this, $func);
         $res->push($inspect);
     }
     return $res;
 }
 function addClassNameToOrderItems_150()
 {
     $explanation = "\r\n\t\t\t<h1>150. Add a class name to all buyables.</h1>\r\n\t\t\t<p>ClassNames used to be implied, this is now saved as OrderItem.BuyableClassName.</p>\r\n\t\t";
     if ($this->retrieveInfoOnly) {
         return $explanation;
     } else {
         echo $explanation;
     }
     $rows = DB::query("\r\n\t\t\tSELECT \"OrderAttribute\".\"ID\", \"ClassName\"\r\n\t\t\tFROM \"OrderAttribute\"\r\n\t\t\t\tINNER JOIN \"OrderItem\" ON \"OrderItem\".\"ID\" = \"OrderAttribute\".\"ID\"\r\n\t\t\tWHERE \"BuyableClassName\" = '' OR \"BuyableClassName\" IS NULL;\r\n\t\t");
     if ($rows) {
         foreach ($rows as $row) {
             $orderItemPostFix = "_OrderItem";
             $id = $row["ID"];
             $className = str_replace($orderItemPostFix, "", $row["ClassName"]);
             if (class_exists($className) && ClassInfo::is_subclass_of($className, "DataObject")) {
                 DB::query("\r\n\t\t\t\t\t\tUPDATE \"OrderItem\"\r\n\t\t\t\t\t\tSET \"BuyableClassName\" = '{$className}'\r\n\t\t\t\t\t\tWHERE \"ID\" = {$id};\r\n\t\t\t\t\t");
                 $this->DBAlterationMessageNow("Updating Order.BuyableClassName ( ID = {$id} ) to {$className}.", "created");
             } else {
                 $this->DBAlterationMessageNow("Order Item with ID = {$id} does not have a valid class name. This needs investigation.", "deleted");
             }
         }
     } else {
         $this->DBAlterationMessageNow("No order items could be found that need updating.");
     }
     return 0;
 }
 protected function storeCustomModelClass()
 {
     if (isset($_REQUEST['CustomModelClass']) && ClassInfo::is_subclass_of($_REQUEST['CustomModelClass'], $this->modelClass)) {
         Session::set($this->class . ".CustomModelClass", $_REQUEST['CustomModelClass']);
     }
 }