Merge pull request #1962 from wilr/api-links

Update @package, @subpackage labels
This commit is contained in:
Ingo Schommer 2013-05-21 03:27:22 -07:00
commit 30906c8b31
41 changed files with 707 additions and 257 deletions

View File

@ -6,8 +6,8 @@
* This is essentially an abstract class which should be subclassed. * This is essentially an abstract class which should be subclassed.
* See {@link CMSMain} for a good example. * See {@link CMSMain} for a good example.
* *
* @package cms * @package framework
* @subpackage core * @subpackage admin
*/ */
class LeftAndMain extends Controller implements PermissionProvider { class LeftAndMain extends Controller implements PermissionProvider {
@ -1769,6 +1769,9 @@ class LeftAndMainMarkingFilter {
/** /**
* Allow overriding finished state for faux redirects. * Allow overriding finished state for faux redirects.
*
* @package framework
* @subpackage admin
*/ */
class LeftAndMain_HTTPResponse extends SS_HTTPResponse { class LeftAndMain_HTTPResponse extends SS_HTTPResponse {
@ -1788,7 +1791,10 @@ class LeftAndMain_HTTPResponse extends SS_HTTPResponse {
* Wrapper around objects being displayed in a tree. * Wrapper around objects being displayed in a tree.
* Caution: Volatile API. * Caution: Volatile API.
* *
* @todo Implement recursive tree node rendering * @todo Implement recursive tree node rendering.
*
* @package framework
* @subpackage admin
*/ */
class LeftAndMain_TreeNode extends ViewableData { class LeftAndMain_TreeNode extends ViewableData {

View File

@ -2,8 +2,8 @@
/** /**
* Plug-ins for additional functionality in your LeftAndMain classes. * Plug-ins for additional functionality in your LeftAndMain classes.
* *
* @package cms * @package framework
* @subpackage core * @subpackage admin
*/ */
abstract class LeftAndMainExtension extends Extension { abstract class LeftAndMainExtension extends Extension {

View File

@ -26,8 +26,8 @@
* *
* @uses SearchContext * @uses SearchContext
* *
* @package cms * @package framework
* @subpackage core * @subpackage admin
*/ */
abstract class ModelAdmin extends LeftAndMain { abstract class ModelAdmin extends LeftAndMain {

View File

@ -1,14 +1,21 @@
<?php <?php
/** /**
* Handle the X-Pjax header that AJAX responses may provide, returning the * Handle the X-Pjax header that AJAX responses may provide, returning the
* fragment, or, in the case of non-AJAX form submissions, redirecting back to the submitter. * fragment, or, in the case of non-AJAX form submissions, redirecting back
* to the submitter.
*
* X-Pjax ensures that users won't end up seeing the unstyled form HTML in
* their browser.
*
* If a JS error prevents the Ajax overriding of form submissions from happening.
* *
* X-Pjax ensures that users won't end up seeing the unstyled form HTML in their browser
* If a JS error prevents the Ajax overriding of form submissions from happening.
* It also provides better non-JS operation. * It also provides better non-JS operation.
* *
* Caution: This API is volatile, and might eventually be replaced by a generic * Caution: This API is volatile, and might eventually be replaced by a generic
* action helper system for controllers. * action helper system for controllers.
*
* @package framework
* @subpackage control
*/ */
class PjaxResponseNegotiator { class PjaxResponseNegotiator {

View File

@ -1,10 +1,8 @@
<?php <?php
/** /**
* Description of RequestProcessor * @package framework
* * @subpackage control
* @author marcus@silverstripe.com.au
* @license BSD License http://silverstripe.org/bsd-license/
*/ */
class RequestProcessor { class RequestProcessor {

View File

@ -2,13 +2,10 @@
/** /**
* A class that proxies another, allowing various functionality to be * A class that proxies another, allowing various functionality to be
* injected * injected.
* *
* @author marcus@silverstripe.com.au
* @package framework * @package framework
* @subpackage injector * @subpackage injector
*
* @license http://silverstripe.org/bsd-license/
*/ */
class AopProxyService { class AopProxyService {
public $beforeCall = array(); public $beforeCall = array();

View File

@ -1,15 +1,13 @@
<?php <?php
/** /**
* A BeforeCallAspect is run before a method is executed * A BeforeCallAspect is run before a method is executed.
* *
* This is a declared interface, but isn't actually required * This is a declared interface, but isn't actually required
* as PHP doesn't really care about types... * as PHP doesn't really care about types...
* *
* @author Marcus Nyeholt <marcus@silverstripe.com.au>
* @package framework * @package framework
* @subpackage injector * @subpackage injector
* @license BSD http://silverstripe.org/BSD-license
*/ */
interface BeforeCallAspect { interface BeforeCallAspect {

View File

@ -0,0 +1,26 @@
<?php
/**
* A class for creating new objects by the injector.
*
* @package framework
* @subpackage injector
*/
class InjectionCreator {
/**
* @param string $object
* A string representation of the class to create
* @param array $params
* An array of parameters to be passed to the constructor
*/
public function create($class, $params = array()) {
$reflector = new ReflectionClass($class);
if (count($params)) {
return $reflector->newInstanceArgs($params);
}
return $reflector->newInstance();
}
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Used to locate configuration for a particular named service.
*
* If it isn't found, return null.
*
* @package framework
* @subpackage injector
*/
class ServiceConfigurationLocator {
public function locateConfigFor($name) {
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* @package framework
* @subpackage injector
*/
class SilverStripeInjectionCreator {
/**
*
* @param string $object
* A string representation of the class to create
* @param array $params
* An array of parameters to be passed to the constructor
*/
public function create($class, $params = array()) {
$class = Object::getCustomClass($class);
$reflector = new ReflectionClass($class);
return $reflector->newInstanceArgs($params);
}
}

View File

@ -0,0 +1,49 @@
<?php
/**
* Use the SilverStripe configuration system to lookup config for a
* particular service.
*
* @package framework
* @subpackage injector
*/
class SilverStripeServiceConfigurationLocator {
private $configs = array();
public function locateConfigFor($name) {
if (isset($this->configs[$name])) {
return $this->configs[$name];
}
$config = Config::inst()->get('Injector', $name);
if ($config) {
$this->configs[$name] = $config;
return $config;
}
// do parent lookup if it's a class
if (class_exists($name)) {
$parents = array_reverse(array_keys(ClassInfo::ancestry($name)));
array_shift($parents);
foreach ($parents as $parent) {
// have we already got for this?
if (isset($this->configs[$parent])) {
return $this->configs[$parent];
}
$config = Config::inst()->get('Injector', $parent);
if ($config) {
$this->configs[$name] = $config;
return $config;
} else {
$this->configs[$parent] = false;
}
}
// there is no parent config, so we'll record that as false so we don't do the expensive
// lookup through parents again
$this->configs[$name] = false;
}
}
}

View File

@ -10,166 +10,215 @@
* - An array * - An array
* - A non-array value * - A non-array value
* *
* If the value is an array, each value in the array may also be one of those three types * If the value is an array, each value in the array may also be one of those
* three types.
* *
* A property can have a value specified in multiple locations, each of which have a hardcoded or explicit priority. * A property can have a value specified in multiple locations, each of which
* We combine all these values together into a "composite" value using rules that depend on the priority order of the * have a hard coded or explicit priority. We combine all these values together
* locations to give the final value, using these rules: * into a "composite" value using rules that depend on the priority order of
* the locations to give the final value, using these rules:
* *
* - If the value is an array, each array is added to the _beginning_ of the composite array in ascending priority * - If the value is an array, each array is added to the _beginning_ of the
* order. If a higher priority item has a non-integer key which is the same as a lower priority item, the value of * composite array in ascending priority order. If a higher priority item has
* those items is merged using these same rules, and the result of the merge is located in the same location the * a non-integer key which is the same as a lower priority item, the value of
* higher priority item would be if there was no key clash. Other than in this key-clash situation, within the * those items is merged using these same rules, and the result of the merge
* particular array, order is preserved. * is located in the same location the higher priority item would be if there
* was no key clash. Other than in this key-clash situation, within the
* particular array, order is preserved.
* *
* - If the value is not an array, the highest priority value is used without any attempt to merge * - If the value is not an array, the highest priority value is used without
* any attempt to merge.
* *
* It is an error to have mixed types of the same named property in different locations (but an error will not * It is an error to have mixed types of the same named property in different
* necessarily be raised due to optimisations in the lookup code) * locations (but an error will not necessarily be raised due to optimizations
* in the lookup code).
* *
* The exception to this is "false-ish" values - empty arrays, empty strings, etc. When merging a non-false-ish value * The exception to this is "false-ish" values - empty arrays, empty strings,
* with a false-ish value, the result will be the non-false-ish value regardless of priority. When merging two * etc. When merging a non-false-ish value with a false-ish value, the result
* will be the non-false-ish value regardless of priority. When merging two
* false-ish values the result will be the higher priority false-ish value. * false-ish values the result will be the higher priority false-ish value.
* *
* The locations that configuration values are taken from in highest -> lowest priority order * The locations that configuration values are taken from in highest -> lowest
* priority order.
* *
* - Any values set via a call to Config#update * - Any values set via a call to Config#update.
* *
* - The configuration values taken from the YAML files in _config directories (internally sorted in before / after * - The configuration values taken from the YAML files in _config directories
* order, where the item that is latest is highest priority) * (internally sorted in before / after order, where the item that is latest
* is highest priority).
* *
* - Any static set on an "additional static source" class (such as an extension) named the same as the name of the * - Any static set on an "additional static source" class (such as an
* property * extension) named the same as the name of the property.
* *
* - Any static set on the class named the same as the name of the property * - Any static set on the class named the same as the name of the property.
* *
* - The composite configuration value of the parent class of this class * - The composite configuration value of the parent class of this class.
* *
* At some of these levels you can also set masks. These remove values from the composite value at their priority * At some of these levels you can also set masks. These remove values from the
* point rather than add. They are much simpler. They consist of a list of key / value pairs. When applied against the * composite value at their priority point rather than add. They are much
* current composite value: * simpler. They consist of a list of key / value pairs. When applied against
* the current composite value:
* *
* - If the composite value is a sequential array, any member of that array that matches any value in the mask is * - If the composite value is a sequential array, any member of that array
* removed * that matches any value in the mask is removed.
* *
* - If the composite value is an associative array, any member of that array that matches both the key and value of * - If the composite value is an associative array, any member of that array
* any pair in the mask is removed * that matches both the key and value of any pair in the mask is removed.
* *
* - If the composite value is not an array, if that value matches any value in the mask it is removed * - If the composite value is not an array, if that value matches any value
* in the mask it is removed.
*
* @package framework
* @subpackage core
*/ */
class Config { class Config {
/** /**
* [A marker instance for the "anything" singleton value. Don't access directly, even in-class, always use * A marker instance for the "anything" singleton value. Don't access
* self::anything() * directly, even in-class, always use self::anything()
*
* @var Object * @var Object
*/ */
static private $_anything = null; private static $_anything = null;
/** /**
* Get a marker class instance that is used to do a "remove anything with this key" by adding * Get a marker class instance that is used to do a "remove anything with
* $key => Config::anything() to the suppress array * this key" by adding $key => Config::anything() to the suppress array
* *
* @todo Does this follow the SS coding conventions? Config::get_anything_marker_instance() is a lot less elegant.
* @return Object * @return Object
*/ */
static public function anything() { public static function anything() {
if (self::$_anything === null) self::$_anything = new stdClass(); if (self::$_anything === null) {
self::$_anything = new stdClass();
}
return self::$_anything; return self::$_anything;
} }
// -- Source options bitmask -- // -- Source options bitmask --
/** /**
* source options bitmask value - merge all parent configuration in as lowest priority * source options bitmask value - merge all parent configuration in as
* lowest priority.
*
* @const * @const
*/ */
const INHERITED = 0; const INHERITED = 0;
/** /**
* source options bitmask value - only get configuration set for this specific class, not any of it's parents * source options bitmask value - only get configuration set for this
* specific class, not any of it's parents.
*
* @const * @const
*/ */
const UNINHERITED = 1; const UNINHERITED = 1;
/** /**
* source options bitmask value - inherit, but stop on the first class that actually provides a value (event an * source options bitmask value - inherit, but stop on the first class
* empty value) * that actually provides a value (event an empty value).
*
* @const * @const
*/ */
const FIRST_SET = 2; const FIRST_SET = 2;
/** @const source options bitmask value - do not use additional statics sources (such as extension) */
/**
* @const source options bitmask value - do not use additional statics
* sources (such as extension)
*/
const EXCLUDE_EXTRA_SOURCES = 4; const EXCLUDE_EXTRA_SOURCES = 4;
// -- get_value_type response enum -- // -- get_value_type response enum --
/** /**
* Return flag for get_value_type indicating value is a scalar (or really just not-an-array, at least ATM) * Return flag for get_value_type indicating value is a scalar (or really
* just not-an-array, at least ATM)
*
* @const * @const
*/ */
const ISNT_ARRAY = 1; const ISNT_ARRAY = 1;
/** /**
* Return flag for get_value_type indicating value is an array * Return flag for get_value_type indicating value is an array.
* @const * @const
*/ */
const IS_ARRAY = 2; const IS_ARRAY = 2;
/** /**
* Get whether the value is an array or not. Used to be more complicated, but still nice sugar to have an enum * Get whether the value is an array or not. Used to be more complicated,
* to compare and not just a true/false value * but still nice sugar to have an enum to compare and not just a true /
* false value.
*
* @param $val any - The value * @param $val any - The value
*
* @return int - One of ISNT_ARRAY or IS_ARRAY * @return int - One of ISNT_ARRAY or IS_ARRAY
*/ */
static protected function get_value_type($val) { protected static function get_value_type($val) {
if (is_array($val)) return self::IS_ARRAY; if (is_array($val)) {
return self::IS_ARRAY;
}
return self::ISNT_ARRAY; return self::ISNT_ARRAY;
} }
/** /**
* What to do if there's a type mismatch * What to do if there's a type mismatch.
*
* @throws UnexpectedValueException * @throws UnexpectedValueException
*/ */
static protected function type_mismatch() { protected static function type_mismatch() {
throw new UnexpectedValueException('Type mismatch in configuration. All values for a particular property must' throw new UnexpectedValueException('Type mismatch in configuration. All values for a particular property must'
. ' contain the same type (or no value at all).'); . ' contain the same type (or no value at all).');
} }
/* @todo If we can, replace next static & static methods with DI once that's in */ /**
static protected $instance; * @todo If we can, replace next static & static methods with DI once that's in
*/
protected static $instance;
/** /**
* Get the current active Config instance. * Get the current active Config instance.
* *
* Configs should not normally be manually created. * Configs should not normally be manually created.
* In general use you will use this method to obtain the current Config instance. *
* In general use you will use this method to obtain the current Config
* instance.
* *
* @return Config * @return Config
*/ */
static public function inst() { public static function inst() {
if (!self::$instance) self::$instance = new Config(); if (!self::$instance) {
self::$instance = new Config();
}
return self::$instance; return self::$instance;
} }
/** /**
* Set the current active Config instance. * Set the current active {@link Config} instance.
* *
* Configs should not normally be manually created. * {@link Config} objects should not normally be manually created.
* A use case for replacing the active configuration set would be for creating an isolated environment for *
* unit tests * A use case for replacing the active configuration set would be for
* creating an isolated environment for unit tests.
* *
* @return Config * @return Config
*/ */
static public function set_instance($instance) { public static function set_instance($instance) {
self::$instance = $instance; self::$instance = $instance;
global $_SINGLETONS; global $_SINGLETONS;
$_SINGLETONS['Config'] = $instance; $_SINGLETONS['Config'] = $instance;
} }
/** /**
* Make the newly active Config be a copy of the current active Config instance. * Make the newly active {@link Config} be a copy of the current active
* {@link Config} instance.
* *
* You can then make changes to the configuration by calling update and remove on the new * You can then make changes to the configuration by calling update and
* value returned by Config::inst(), and then discard those changes later by calling unnest * remove on the new value returned by Config::inst(), and then discard
* those changes later by calling unnest.
*/ */
static public function nest() { public static function nest() {
$current = self::$instance; $current = self::$instance;
$new = clone $current; $new = clone $current;
@ -178,17 +227,21 @@ class Config {
} }
/** /**
* Change the active Config back to the Config instance the current active Config object * Change the active Config back to the Config instance the current active
* was copied from * Config object was copied from.
*/ */
static public function unnest() { public static function unnest() {
self::set_instance(self::$instance->nestedFrom); self::set_instance(self::$instance->nestedFrom);
} }
/**
* @var array
*/
protected $cache; protected $cache;
/** /**
* Each copy of the Config object need's it's own cache, so changes don't leak through to other instances * Each copy of the Config object need's it's own cache, so changes don't
* leak through to other instances.
*/ */
public function __construct() { public function __construct() {
$this->cache = new Config_LRU(); $this->cache = new Config_LRU();
@ -198,21 +251,37 @@ class Config {
$this->cache = clone $this->cache; $this->cache = clone $this->cache;
} }
/** @var Config - The config instance this one was copied from when Config::nest() was called */ /**
* @var Config - The config instance this one was copied from when
* Config::nest() was called.
*/
protected $nestedFrom = null; protected $nestedFrom = null;
/** @var [array] - Array of arrays. Each member is an nested array keyed as $class => $name => $value, /**
* where value is a config value to treat as the highest priority item */ * @var array - Array of arrays. Each member is an nested array keyed as
* $class => $name => $value, where value is a config value to treat as
* the highest priority item.
*/
protected $overrides = array(); protected $overrides = array();
/** @var [array] - Array of arrays. Each member is an nested array keyed as $class => $name => $value, /**
* where value is a config value suppress from any lower priority item */ * @var array $suppresses Array of arrays. Each member is an nested array
* keyed as $class => $name => $value, where value is a config value suppress
* from any lower priority item.
*/
protected $suppresses = array(); protected $suppresses = array();
/**
* @var array
*/
protected $staticManifests = array(); protected $staticManifests = array();
/**
* @param SS_ConfigStaticManifest
*/
public function pushConfigStaticManifest(SS_ConfigStaticManifest $manifest) { public function pushConfigStaticManifest(SS_ConfigStaticManifest $manifest) {
array_unshift($this->staticManifests, $manifest); array_unshift($this->staticManifests, $manifest);
$this->cache->clean(); $this->cache->clean();
} }
@ -596,6 +665,10 @@ class Config {
} }
/**
* @package framework
* @subpackage core
*/
class Config_LRU { class Config_LRU {
const SIZE = 1000; const SIZE = 1000;
@ -701,25 +774,54 @@ class Config_LRU {
} }
} }
/**
* @package framework
* @subpackage core
*/
class Config_ForClass { class Config_ForClass {
/**
* @var string $class
*/
protected $class; protected $class;
/**
* @param string $class
*/
public function __construct($class) { public function __construct($class) {
$this->class = $class; $this->class = $class;
} }
/**
* @param string $name
*/
public function __get($name) { public function __get($name) {
return Config::inst()->get($this->class, $name); return Config::inst()->get($this->class, $name);
} }
/**
* @param string $name
* @param mixed $val
*/
public function __set($name, $val) { public function __set($name, $val) {
return Config::inst()->update($this->class, $name, $val); return Config::inst()->update($this->class, $name, $val);
} }
/**
* @param string $name
* @param int $sourceOptions
*
* @return array|scalar
*/
public function get($name, $sourceOptions = 0) { public function get($name, $sourceOptions = 0) {
return Config::inst()->get($this->class, $name, $sourceOptions); return Config::inst()->get($this->class, $name, $sourceOptions);
} }
/**
* @param string
*
* @return Config_ForClass
*/
public function forClass($class) { public function forClass($class) {
return Config::inst()->forClass($class); return Config::inst()->forClass($class);
} }

View File

@ -16,7 +16,7 @@
* @see SS_List * @see SS_List
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridField extends FormField { class GridField extends FormField {
@ -761,12 +761,11 @@ class GridField extends FormField {
/** /**
* This class is the base class when you want to have an action that alters the state of the gridfield, * This class is the base class when you want to have an action that alters
* rendered as a button element. * the state of the {@link GridField}, rendered as a button element.
* *
* @package framework * @package framework
* @subpackage forms * @subpackage fields-gridfield
*
*/ */
class GridField_FormAction extends FormAction { class GridField_FormAction extends FormAction {

View File

@ -1,14 +1,25 @@
<?php <?php
/** /**
* This class is is responsible for adding objects to another object's has_many and many_many relation, * This class is is responsible for adding objects to another object's has_many
* as defined by the {@link RelationList} passed to the GridField constructor. * and many_many relation, as defined by the {@link RelationList} passed to the
* Objects can be searched through an input field (partially matching one or more fields). * {@link GridField} constructor.
*
* Objects can be searched through an input field (partially matching one or
* more fields).
*
* Selecting from the results will add the object to the relation. * Selecting from the results will add the object to the relation.
* Often used alongside {@link GridFieldDeleteAction} for detaching existing records from a relatinship. *
* For easier setup, have a look at a sample configuration in {@link GridFieldConfig_RelationEditor}. * Often used alongside {@link GridFieldDeleteAction} for detaching existing
* records from a relationship.
*
* For easier setup, have a look at a sample configuration in
* {@link GridFieldConfig_RelationEditor}.
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldAddExistingAutocompleter class GridFieldAddExistingAutocompleter
implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator, GridField_URLHandler { implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator, GridField_URLHandler {
/** /**
* Which template to use for rendering * Which template to use for rendering

View File

@ -1,10 +1,13 @@
<?php <?php
/** /**
* This component provides a button for opening the add new form provided by {@link GridFieldDetailForm}. * This component provides a button for opening the add new form provided by
* Only returns a button if {@link DataObject->canCreate()} for this record returns true. * {@link GridFieldDetailForm}.
*
* Only returns a button if {@link DataObject->canCreate()} for this record
* returns true.
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldAddNewButton implements GridField_HTMLProvider { class GridFieldAddNewButton implements GridField_HTMLProvider {
@ -14,6 +17,7 @@ class GridFieldAddNewButton implements GridField_HTMLProvider {
public function setButtonName($name) { public function setButtonName($name) {
$this->buttonName = $name; $this->buttonName = $name;
return $this; return $this;
} }
@ -23,7 +27,10 @@ class GridFieldAddNewButton implements GridField_HTMLProvider {
public function getHTMLFragments($gridField) { public function getHTMLFragments($gridField) {
$singleton = singleton($gridField->getModelClass()); $singleton = singleton($gridField->getModelClass());
if(!$singleton->canCreate()) return array();
if(!$singleton->canCreate()) {
return array();
}
if(!$this->buttonName) { if(!$this->buttonName) {
// provide a default button name, can be changed by calling {@link setButtonName()} on this component // provide a default button name, can be changed by calling {@link setButtonName()} on this component

View File

@ -1,14 +1,18 @@
<?php <?php
/** /**
* Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds a buttonrow to that field. * Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds
* a button row to that field.
*
* The button row provides a space for actions on this grid. * The button row provides a space for actions on this grid.
* *
* This row provides two new HTML fragment spaces: 'toolbar-header-left' and 'toolbar-header-right'. * This row provides two new HTML fragment spaces: 'toolbar-header-left' and
* 'toolbar-header-right'.
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldButtonRow implements GridField_HTMLProvider { class GridFieldButtonRow implements GridField_HTMLProvider {
protected $targetFragment; protected $targetFragment;
public function __construct($targetFragment = 'before') { public function __construct($targetFragment = 'before') {
@ -20,6 +24,7 @@ class GridFieldButtonRow implements GridField_HTMLProvider {
"LeftFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-left)", "LeftFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-left)",
"RightFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-right)", "RightFragment" => "\$DefineFragment(buttons-{$this->targetFragment}-right)",
)); ));
return array( return array(
$this->targetFragment => $data->renderWith('GridFieldButtonRow') $this->targetFragment => $data->renderWith('GridFieldButtonRow')
); );

View File

@ -1,42 +1,58 @@
<?php <?php
/** /**
* Base interface for all components that can be added to GridField. * Base interface for all components that can be added to GridField.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridFieldComponent { interface GridFieldComponent {
} }
/** /**
* A GridField manipulator that provides HTML for the header/footer rows, or for before/after the template * A GridField manipulator that provides HTML for the header/footer rows, or f
* or before/after the template.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_HTMLProvider extends GridFieldComponent { interface GridField_HTMLProvider extends GridFieldComponent {
/** /**
* Returns a map where the keys are fragment names and the values are pieces of HTML to add to these fragments. * Returns a map where the keys are fragment names and the values are
* pieces of HTML to add to these fragments.
* *
* Here are 4 built-in fragments: 'header', 'footer', 'before', and 'after', but components may also specify * Here are 4 built-in fragments: 'header', 'footer', 'before', and
* fragments of their own. * 'after', but components may also specify fragments of their own.
* *
* To specify a new fragment, specify a new fragment by including the text "$DefineFragment(fragmentname)" in the * To specify a new fragment, specify a new fragment by including the
* HTML that you return. Fragment names should only contain alphanumerics, -, and _. * text "$DefineFragment(fragmentname)" in the HTML that you return.
* *
* If you attempt to return HTML for a fragment that doesn't exist, an exception will be thrown when the GridField * Fragment names should only contain alphanumerics, -, and _.
* is rendered.
* *
* @return Array * If you attempt to return HTML for a fragment that doesn't exist, an
* exception will be thrown when the {@link GridField} is rendered.
*
* @return array
*/ */
public function getHTMLFragments($gridField); public function getHTMLFragments($gridField);
} }
/** /**
* Add a new column to the table display body, or modify existing columns. * Add a new column to the table display body, or modify existing columns.
*
* Used once per record/row. * Used once per record/row.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_ColumnProvider extends GridFieldComponent { interface GridField_ColumnProvider extends GridFieldComponent {
/** /**
* Modify the list of columns displayed in the table. * Modify the list of columns displayed in the table.
* See {@link GridFieldDataColumns->getDisplayFields()} and {@link GridFieldDataColumns}. *
* @see {@link GridFieldDataColumns->getDisplayFields()}
* @see {@link GridFieldDataColumns}.
* *
* @param GridField $gridField * @param GridField $gridField
* @param array - List reference of all column names. * @param array - List reference of all column names.
@ -83,16 +99,29 @@ interface GridField_ColumnProvider extends GridFieldComponent {
} }
/** /**
* An action is defined by two things: an action name, and zero or more named arguments. * An action is defined by two things: an action name, and zero or more named
* arguments.
*
* There is no built-in notion of a record-specific or column-specific action, * There is no built-in notion of a record-specific or column-specific action,
* but you may choose to define an argument such as ColumnName or RecordID in order to implement these. * but you may choose to define an argument such as ColumnName or RecordID in
* Does not provide interface elements to call those actions, see {@link GridField_FormAction}. * order to implement these.
*
* Does not provide interface elements to call those actions.
*
* @see {@link GridField_FormAction}.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_ActionProvider extends GridFieldComponent { interface GridField_ActionProvider extends GridFieldComponent {
/** /**
* Return a list of the actions handled by this action provider. * Return a list of the actions handled by this action provider.
* Used to identify the action later on through the $actionName parameter in {@link handleAction}. *
* There is no namespacing on these actions, so you need to ensure that they don't conflict with other components. * Used to identify the action later on through the $actionName parameter
* in {@link handleAction}.
*
* There is no namespacing on these actions, so you need to ensure that
* they don't conflict with other components.
* *
* @param GridField * @param GridField
* @return Array with action identifier strings. * @return Array with action identifier strings.
@ -100,9 +129,10 @@ interface GridField_ActionProvider extends GridFieldComponent {
public function getActions($gridField); public function getActions($gridField);
/** /**
* Handle an action on the given grid field. * Handle an action on the given {@link GridField}.
* Calls ALL components for every action handled, so the component *
* needs to ensure it only accepts actions it is actually supposed to handle. * Calls ALL components for every action handled, so the component needs
* to ensure it only accepts actions it is actually supposed to handle.
* *
* @param GridField * @param GridField
* @param String Action identifier, see {@link getActions()}. * @param String Action identifier, see {@link getActions()}.
@ -113,14 +143,21 @@ interface GridField_ActionProvider extends GridFieldComponent {
} }
/** /**
* Can modify the data list. * Can modify the data list.
* For example, a paginating component can apply a limit, or a sorting component can apply a sort. *
* Generally, the data manipulator will make use of to `GridState` variables to decide * For example, a paginating component can apply a limit, or a sorting
* how to modify the data list (see {@link GridState}). * component can apply a sort.
*
* Generally, the data manipulator will make use of to {@link GridState}
* variables to decide how to modify the {@link DataList}.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_DataManipulator extends GridFieldComponent { interface GridField_DataManipulator extends GridFieldComponent {
/** /**
* Manipulate the datalist as needed by this grid modifier. * Manipulate the {@link DataList} as needed by this grid modifier.
* *
* @param GridField * @param GridField
* @param SS_List * @param SS_List
@ -130,21 +167,37 @@ interface GridField_DataManipulator extends GridFieldComponent {
} }
/** /**
* Sometimes an action isn't enough: you need to provide additional support URLs for the grid. * Sometimes an action isn't enough: you need to provide additional support
* These URLs may return user-visible content, for example a pop-up form for editing a record's details, * URLs for the {@link GridField}.
* or they may be support URLs for front-end functionality. *
* For example a URL that will return JSON-formatted data for a javascript grid control. * These URLs may return user-visible content, for example a pop-up form for
* editing a record's details, or they may be support URLs for front-end
* functionality.
*
* For example a URL that will return JSON-formatted data for a javascript
* grid control.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_URLHandler extends GridFieldComponent { interface GridField_URLHandler extends GridFieldComponent {
/** /**
* Return URLs to be handled by this grid field, in an array the same form as $url_handlers. * Return URLs to be handled by this grid field, in an array the same form
* Handler methods will be called on the component, rather than the grid field. * as $url_handlers.
*
* Handler methods will be called on the component, rather than the
* {@link GridField}.
*/ */
public function getURLHandlers($gridField); public function getURLHandlers($gridField);
} }
/** /**
* A component which is used to handle when a grid field is saved into a record. * A component which is used to handle when a {@link GridField} is saved into
* a record.
*
* @package framework
* @subpackage fields-gridfield
*/ */
interface GridField_SaveHandler extends GridFieldComponent { interface GridField_SaveHandler extends GridFieldComponent {

View File

@ -1,21 +1,27 @@
<?php <?php
/** /**
* Encapsulates a collection of components following the {@link GridFieldComponent} interface. * Encapsulates a collection of components following the
* While the {@link GridField} itself has some configuration in the form of setters, * {@link GridFieldComponent} interface. While the {@link GridField} itself
* most of the details are dealt with through components. * has some configuration in the form of setters, most of the details are
* dealt with through components.
* *
* For example, you would add a {@link GridFieldPaginator} component to enable * For example, you would add a {@link GridFieldPaginator} component to enable
* pagination on the listed records, and configure it through {@link GridFieldPaginator->setItemsPerPage()}. * pagination on the listed records, and configure it through
* {@link GridFieldPaginator->setItemsPerPage()}.
* *
* In order to reduce the amount of custom code required, the framework provides * In order to reduce the amount of custom code required, the framework
* some default configurations for common use cases: * provides some default configurations for common use cases:
*
* - {@link GridFieldConfig_Base} (added by default to GridField) * - {@link GridFieldConfig_Base} (added by default to GridField)
* - {@link GridFieldConfig_RecordEditor} * - {@link GridFieldConfig_RecordEditor}
* - {@link GridFieldConfig_RelationEditor} * - {@link GridFieldConfig_RelationEditor}
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldConfig { class GridFieldConfig {
/** /**
*
* @var ArrayList * @var ArrayList
*/ */
protected $components = null; protected $components = null;
@ -129,12 +135,15 @@ class GridFieldConfig {
} }
/** /**
* A simple readonly, paginated view of records, * A simple readonly, paginated view of records, with sortable and searchable
* with sortable and searchable headers. * headers.
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldConfig_Base extends GridFieldConfig { class GridFieldConfig_Base extends GridFieldConfig {
/** /**
*
* @param int $itemsPerPage - How many items per page should show up * @param int $itemsPerPage - How many items per page should show up
*/ */
public function __construct($itemsPerPage=null) { public function __construct($itemsPerPage=null) {
@ -153,6 +162,9 @@ class GridFieldConfig_Base extends GridFieldConfig {
/** /**
* Allows viewing readonly details of individual records. * Allows viewing readonly details of individual records.
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldConfig_RecordViewer extends GridFieldConfig_Base { class GridFieldConfig_RecordViewer extends GridFieldConfig_Base {
@ -166,7 +178,8 @@ class GridFieldConfig_RecordViewer extends GridFieldConfig_Base {
} }
/** /**
* * @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldConfig_RecordEditor extends GridFieldConfig { class GridFieldConfig_RecordEditor extends GridFieldConfig {
/** /**
@ -195,22 +208,28 @@ class GridFieldConfig_RecordEditor extends GridFieldConfig {
/** /**
* Similar to {@link GridFieldConfig_RecordEditor}, but adds features * Similar to {@link GridFieldConfig_RecordEditor}, but adds features to work
* to work on has-many or many-many relationships. * on has-many or many-many relationships.
* Allows to search for existing records to add to the relationship, *
* detach listed records from the relationship (rather than removing them from the database), * Allows to search for existing records to add to the relationship, detach
* and automatically add newly created records to it. * listed records from the relationship (rather than removing them from the
* database), and automatically add newly created records to it.
* *
* To further configure the field, use {@link getComponentByType()}, * To further configure the field, use {@link getComponentByType()}, for
* for example to change the field to search. * example to change the field to search.
*
* <code> * <code>
* GridFieldConfig_RelationEditor::create() * GridFieldConfig_RelationEditor::create()
* ->getComponentByType('GridFieldAddExistingAutocompleter')->setSearchFields('MyField'); * ->getComponentByType('GridFieldAddExistingAutocompleter')
* ->setSearchFields('MyField');
* </code> * </code>
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldConfig_RelationEditor extends GridFieldConfig { class GridFieldConfig_RelationEditor extends GridFieldConfig {
/** /**
*
* @param int $itemsPerPage - How many items per page should show up * @param int $itemsPerPage - How many items per page should show up
*/ */
public function __construct($itemsPerPage=null) { public function __construct($itemsPerPage=null) {

View File

@ -1,17 +1,20 @@
<?php <?php
/** /**
*
* @see GridField * @see GridField
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridFieldDataColumns implements GridField_ColumnProvider { class GridFieldDataColumns implements GridField_ColumnProvider {
/** @var array */ /**
* @var array
*/
public $fieldCasting = array(); public $fieldCasting = array();
/** @var array */ /**
* @var array
*/
public $fieldFormatting = array(); public $fieldFormatting = array();
/** /**

View File

@ -1,24 +1,31 @@
<?php <?php
/** /**
* This class is a {@link GridField} component that adds a delete action for objects. * This class is a {@link GridField} component that adds a delete action for
* objects.
*
* This component also supports unlinking a relation instead of deleting the
* object.
* *
* This component also supports unlinking a relation instead of deleting the object.
* Use the {@link $removeRelation} property set in the constructor. * Use the {@link $removeRelation} property set in the constructor.
* *
* <code> * <code>
* $action = new GridFieldDeleteAction(); // delete objects permanently * $action = new GridFieldDeleteAction(); // delete objects permanently
* $action = new GridFieldDeleteAction(true); // removes the relation to object, instead of deleting *
* // removes the relation to object instead of deleting
* $action = new GridFieldDeleteAction(true);
* </code> * </code>
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider { class GridFieldDeleteAction implements GridField_ColumnProvider, GridField_ActionProvider {
/** /**
* If this is set to true, this actionprovider will remove the object from the list, instead of * If this is set to true, this {@link GridField_ActionProvider} will
* deleting. In the case of a has one, has many or many many list it will uncouple the item from * remove the object from the list, instead of deleting.
* the list. *
* In the case of a has one, has many or many many list it will uncouple
* the item from the list.
* *
* @var boolean * @var boolean
*/ */

View File

@ -1,14 +1,20 @@
<?php <?php
/** /**
* Provides view and edit forms at GridField-specific URLs. * Provides view and edit forms at GridField-specific URLs.
*
* These can be placed into pop-ups by an appropriate front-end. * These can be placed into pop-ups by an appropriate front-end.
* Usually added to a grid field alongside of {@link GridFieldEditButton} *
* which takes care of linking the individual rows to their edit view. * Usually added to a {@link GridField} alongside of a
* {@link GridFieldEditButton} which takes care of linking the
* individual rows to their edit view.
* *
* The URLs provided will be off the following form: * The URLs provided will be off the following form:
* - <FormURL>/field/<GridFieldName>/item/<RecordID> * - <FormURL>/field/<GridFieldName>/item/<RecordID>
* - <FormURL>/field/<GridFieldName>/item/<RecordID>/edit * - <FormURL>/field/<GridFieldName>/item/<RecordID>/edit
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldDetailForm implements GridField_URLHandler { class GridFieldDetailForm implements GridField_URLHandler {
@ -183,6 +189,10 @@ class GridFieldDetailForm implements GridField_URLHandler {
} }
} }
/**
* @package framework
* @subpackage fields-gridfield
*/
class GridFieldDetailForm_ItemRequest extends RequestHandler { class GridFieldDetailForm_ItemRequest extends RequestHandler {
/** /**

View File

@ -1,10 +1,17 @@
<?php <?php
/** /**
* Provides the entry point to editing a single record presented by the grid. * Provides the entry point to editing a single record presented by the
* Doesn't show an edit view on its own or modifies the record, but rather relies on routing conventions * {@link GridField}.
* established in {@link getColumnContent()}. The default routing applies to *
* the {@link GridFieldDetailForm} component, which has to be added separately * Doesn't show an edit view on its own or modifies the record, but rather
* to the grid field configuration. * relies on routing conventions established in {@link getColumnContent()}.
*
* The default routing applies to the {@link GridFieldDetailForm} component,
* which has to be added separately to the {@link GridField} configuration.
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldEditButton implements GridField_ColumnProvider { class GridFieldEditButton implements GridField_ColumnProvider {
@ -55,7 +62,7 @@ class GridFieldEditButton implements GridField_ColumnProvider {
} }
/** /**
* Which GridField actions are this component handling * Which GridField actions are this component handling.
* *
* @param GridField $gridField * @param GridField $gridField
* @return array * @return array
@ -65,10 +72,10 @@ class GridFieldEditButton implements GridField_ColumnProvider {
} }
/** /**
*
* @param GridField $gridField * @param GridField $gridField
* @param DataObject $record * @param DataObject $record
* @param string $columnName * @param string $columnName
*
* @return string - the HTML for the column * @return string - the HTML for the column
*/ */
public function getColumnContent($gridField, $record, $columnName) { public function getColumnContent($gridField, $record, $columnName) {
@ -83,12 +90,13 @@ class GridFieldEditButton implements GridField_ColumnProvider {
} }
/** /**
* Handle the actions and apply any changes to the GridField * Handle the actions and apply any changes to the GridField.
* *
* @param GridField $gridField * @param GridField $gridField
* @param string $actionName * @param string $actionName
* @param mixed $arguments * @param mixed $arguments
* @param array $data - form data * @param array $data - form data
*
* @return void * @return void
*/ */
public function handleAction(GridField $gridField, $actionName, $arguments, $data) { public function handleAction(GridField $gridField, $actionName, $arguments, $data) {

View File

@ -1,12 +1,12 @@
<?php <?php
/**
* @package framework
* @subpackage gridfield
*/
/** /**
* Adds an "Export list" button to the bottom of a GridField. * Adds an "Export list" button to the bottom of a {@link GridField}.
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler { class GridFieldExportButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler {
/** /**

View File

@ -1,11 +1,12 @@
<?php <?php
/** /**
* GridFieldFilterHeader alters the gridfield with some filtering fields in the header of each column * GridFieldFilterHeader alters the {@link GridField} with some filtering
* fields in the header of each column.
* *
* @see GridField * @see GridField
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider { class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {

View File

@ -1,13 +1,19 @@
<?php <?php
/** /**
* Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds a footer bar to that field. * Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds
* The footer looks just like the {@link GridFieldPaginator} control, except without the pagination controls. * a footer bar to that field.
* It only display the "Viewing 1-8 of 8" status text and (optionally) a configurable status message.
* *
* The purpose of this class is to have a footer that can round off GridField without having to use pagination. * The footer looks just like the {@link GridFieldPaginator} control, except
* without the pagination controls.
*
* It only display the "Viewing 1-8 of 8" status text and (optionally) a
* configurable status message.
*
* The purpose of this class is to have a footer that can round off
* {@link GridField} without having to use pagination.
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldFooter implements GridField_HTMLProvider { class GridFieldFooter implements GridField_HTMLProvider {
@ -21,7 +27,9 @@ class GridFieldFooter implements GridField_HTMLProvider {
* @param string $message - a message to display in the footer * @param string $message - a message to display in the footer
*/ */
public function __construct($message = null) { public function __construct($message = null) {
if($message) $this->message = $message; if($message) {
$this->message = $message;
}
} }
@ -36,7 +44,12 @@ class GridFieldFooter implements GridField_HTMLProvider {
)); ));
return array( return array(
'footer' => $forTemplate->renderWith('GridFieldFooter', array('Colspan'=>count($gridField->getColumns()))), 'footer' => $forTemplate->renderWith(
'GridFieldFooter',
array(
'Colspan' => count($gridField->getColumns())
)
)
); );
} }
} }

View File

@ -1,10 +1,13 @@
<?php <?php
/** /**
* Adds a "level up" link to a GridField table, which is useful * Adds a "level up" link to a GridField table, which is useful when viewing
* when viewing hierarchical data. Requires the managed record * hierarchical data. Requires the managed record to have a "getParent()"
* to have a "getParent()" method or has_one relationship called "Parent". * method or has_one relationship called "Parent".
*
* @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldLevelup extends Object implements GridField_HTMLProvider{ class GridFieldLevelup extends Object implements GridField_HTMLProvider {
/** /**
* @var integer - the record id of the level up to * @var integer - the record id of the level up to

View File

@ -4,10 +4,10 @@
* GridFieldPage displays a simple current page count summary. * GridFieldPage displays a simple current page count summary.
* E.g. "View 1 - 15 of 32" * E.g. "View 1 - 15 of 32"
* *
* Depends on GridFieldPaginator being added to the same gridfield * Depends on {@link GridFieldPaginator} being added to the {@link GridField}.
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridFieldPageCount implements GridField_HTMLProvider { class GridFieldPageCount implements GridField_HTMLProvider {
/** /**

View File

@ -1,10 +1,10 @@
<?php <?php
/** /**
* GridFieldPaginator paginates the gridfields list and adds controlls to the * GridFieldPaginator paginates the {@link GridField} list and adds controls
* bottom of the gridfield. * to the bottom of the {@link GridField}.
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider { class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {

View File

@ -1,11 +1,11 @@
<?php <?php
/** /**
* Adds an "Print" button to the bottom or top of a GridField. * Adds an "Print" button to the bottom or top of a GridField.
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldPrintButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler { class GridFieldPrintButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler {
/** /**

View File

@ -1,11 +1,13 @@
<?php <?php
/** /**
* GridFieldSortableHeader adds column headers to a gridfield that can also sort the columns * GridFieldSortableHeader adds column headers to a {@link GridField} that can
* also sort the columns.
* *
* @see GridField * @see GridField
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider { class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
@ -14,7 +16,9 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
*/ */
protected $throwExceptionOnBadDataType = true; protected $throwExceptionOnBadDataType = true;
/** @var array */ /**
* @var array
*/
public $fieldSorting = array(); public $fieldSorting = array();
/** /**

View File

@ -1,12 +1,16 @@
<?php <?php
/** /**
* Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds a header title to that field. * Adding this class to a {@link GridFieldConfig} of a {@link GridField} adds
* a header title to that field.
*
* The header serves to display the name of the data the GridField is showing. * The header serves to display the name of the data the GridField is showing.
* *
* @package framework * @package framework
* @subpackage gridfield * @subpackage fields-gridfield
*/ */
class GridFieldToolbarHeader implements GridField_HTMLProvider { class GridFieldToolbarHeader implements GridField_HTMLProvider {
public function getHTMLFragments( $gridField) { public function getHTMLFragments( $gridField) {
return array( return array(
'header' => $gridField->renderWith('GridFieldToolbarHeader') 'header' => $gridField->renderWith('GridFieldToolbarHeader')

View File

@ -1,9 +1,11 @@
<?php <?php
/** /**
* A button that allows a user to view readonly details of a record. This is * A button that allows a user to view readonly details of a record. This is
* disabled by default and intended for use in readonly grid fields. * disabled by default and intended for use in readonly {@link GridField}
* instances.
* *
* @package framework * @package framework
* @subpackage fields-gridfield
*/ */
class GridFieldViewButton implements GridField_ColumnProvider { class GridFieldViewButton implements GridField_ColumnProvider {
@ -31,5 +33,4 @@ class GridFieldViewButton implements GridField_ColumnProvider {
public function getColumnMetadata($gridField, $col) { public function getColumnMetadata($gridField, $col) {
return array('title' => null); return array('title' => null);
} }
} }

View File

@ -1,13 +1,14 @@
<?php <?php
/** /**
* This class is a snapshot of the current status of a {@link GridField}. It's * This class is a snapshot of the current status of a {@link GridField}.
* designed to be inserted into a Form as a HiddenField and passed through to *
* actions such as the {@link GridField_FormAction} * It's designed to be inserted into a Form as a HiddenField and passed through
* to actions such as the {@link GridField_FormAction}.
* *
* @see GridField * @see GridField
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridState extends HiddenField { class GridState extends HiddenField {
@ -115,12 +116,13 @@ class GridState extends HiddenField {
} }
/** /**
* Simple set of data, similar to stdClass, but without the notice-level errors. * Simple set of data, similar to stdClass, but without the notice-level
* errors.
* *
* @see GridState * @see GridState
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridState_Data { class GridState_Data {
@ -174,7 +176,7 @@ class GridState_Data {
* @see GridState * @see GridState
* *
* @package framework * @package framework
* @subpackage fields-relational * @subpackage fields-gridfield
*/ */
class GridState_Component implements GridField_HTMLProvider { class GridState_Component implements GridField_HTMLProvider {

View File

@ -991,7 +991,10 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
*/ */
public function removeByID($itemID) { public function removeByID($itemID) {
$item = $this->byID($itemID); $item = $this->byID($itemID);
if($item) return $item->delete();
if($item) {
return $item->delete();
}
} }
/** /**

View File

@ -1,45 +1,73 @@
<?php <?php
/** /**
* Representation of a DataModel - a collection of DataLists for each different data type. * Representation of a DataModel - a collection of DataLists for each different
* data type.
* *
* Usage: * Usage:
* * <code>
* $model = new DataModel; * $model = new DataModel;
* $mainMenu = $model->SiteTree->where('"ParentID" = 0 AND "ShowInMenus" = 1'); * $mainMenu = $model->SiteTree->where('"ParentID" = 0 AND "ShowInMenus" = 1');
* </code>
*
* @package framework
* @subpackage model
*/ */
class DataModel { class DataModel {
/**
* @var DataModel
*/
protected static $inst; protected static $inst;
/**
* @var array $customDataLists
*/
protected $customDataLists = array();
/** /**
* Get the global DataModel. * Get the global DataModel.
*
* @return DataModel
*/ */
public static function inst() { public static function inst() {
if(!self::$inst) self::$inst = new self; if(!self::$inst) {
self::$inst = new self;
}
return self::$inst; return self::$inst;
} }
/** /**
* Set the global DataModel, used when data is requested from static methods. * Set the global DataModel, used when data is requested from static
* methods.
*
* @return DataModel
*/ */
public static function set_inst(DataModel $inst) { public static function set_inst(DataModel $inst) {
self::$inst = $inst; self::$inst = $inst;
} }
//////////////////////////////////////////////////////////////////////// /**
* @param string
protected $customDataLists = array(); *
* @return DataList
*/
public function __get($class) { public function __get($class) {
if(isset($this->customDataLists[$class])) { if(isset($this->customDataLists[$class])) {
return clone $this->customDataLists[$class]; return clone $this->customDataLists[$class];
} else { } else {
$list = DataList::create($class); $list = DataList::create($class);
$list->setDataModel($this); $list->setDataModel($this);
return $list; return $list;
} }
} }
/**
* @param string
* @param DataList
*/
public function __set($class, $item) { public function __set($class, $item) {
$item = clone $item; $item = clone $item;
$item->setDataModel($this); $item->setDataModel($this);

View File

@ -14,7 +14,7 @@
class DataQuery { class DataQuery {
/** /**
* @var String * @var string
*/ */
protected $dataClass; protected $dataClass;
@ -756,11 +756,16 @@ class DataQuery {
/** /**
* Represents a subgroup inside a WHERE clause in a {@link DataQuery} * Represents a subgroup inside a WHERE clause in a {@link DataQuery}
* *
* Stores the clauses for the subgroup inside a specific {@link SQLQuery} object. * Stores the clauses for the subgroup inside a specific {@link SQLQuery}
* object.
*
* All non-where methods call their DataQuery versions, which uses the base * All non-where methods call their DataQuery versions, which uses the base
* query object. * query object.
*
* @package framework
*/ */
class DataQuery_SubGroup extends DataQuery { class DataQuery_SubGroup extends DataQuery {
protected $whereQuery; protected $whereQuery;
public function __construct(DataQuery $base, $connective) { public function __construct(DataQuery $base, $connective) {
@ -790,6 +795,7 @@ class DataQuery_SubGroup extends DataQuery {
if($filter) { if($filter) {
$this->whereQuery->addWhere($filter); $this->whereQuery->addWhere($filter);
} }
return $this; return $this;
} }
@ -806,6 +812,7 @@ class DataQuery_SubGroup extends DataQuery {
if($filter) { if($filter) {
$this->whereQuery->addWhereAny($filter); $this->whereQuery->addWhereAny($filter);
} }
return $this; return $this;
} }
@ -814,8 +821,14 @@ class DataQuery_SubGroup extends DataQuery {
// We always need to have something so we don't end up with something like '... AND () AND ...' // We always need to have something so we don't end up with something like '... AND () AND ...'
return '1=1'; return '1=1';
} }
$sql = DB::getConn()->sqlWhereToString($this->whereQuery->getWhere(), $this->whereQuery->getConnective());
$sql = DB::getConn()->sqlWhereToString(
$this->whereQuery->getWhere(),
$this->whereQuery->getConnective()
);
$sql = preg_replace('[^\s*WHERE\s*]', '', $sql); $sql = preg_replace('[^\s*WHERE\s*]', '', $sql);
return $sql; return $sql;
} }
} }

View File

@ -1,9 +1,13 @@
<?php <?php
/** /**
* Subclass of {@link DataList} representing a has_many relation * Subclass of {@link DataList} representing a has_many relation.
*
* @package framework
* @subpackage model
*/ */
class HasManyList extends RelationList { class HasManyList extends RelationList {
protected $foreignKey; protected $foreignKey;
/** /**
@ -18,6 +22,7 @@ class HasManyList extends RelationList {
*/ */
public function __construct($dataClass, $foreignKey) { public function __construct($dataClass, $foreignKey) {
parent::__construct($dataClass); parent::__construct($dataClass);
$this->foreignKey = $foreignKey; $this->foreignKey = $foreignKey;
} }
@ -36,7 +41,9 @@ class HasManyList extends RelationList {
/** /**
* Adds the item to this relation. * Adds the item to this relation.
*
* It does so by setting the relationFilters. * It does so by setting the relationFilters.
*
* @param $item The DataObject to be added, or its ID * @param $item The DataObject to be added, or its ID
*/ */
public function add($item) { public function add($item) {
@ -66,11 +73,14 @@ class HasManyList extends RelationList {
/** /**
* Remove an item from this relation. * Remove an item from this relation.
*
* Doesn't actually remove the item, it just clears the foreign key value. * Doesn't actually remove the item, it just clears the foreign key value.
* @param $itemID The ID of the item to be removed *
* @param $itemID The ID of the item to be removed.
*/ */
public function removeByID($itemID) { public function removeByID($itemID) {
$item = $this->byID($itemID); $item = $this->byID($itemID);
return $this->remove($item); return $this->remove($item);
} }

View File

@ -1,7 +1,10 @@
<?php <?php
/** /**
* Subclass of {@link DataList} representing a many_many relation * Subclass of {@link DataList} representing a many_many relation.
*
* @package framework
* @subpackage model
*/ */
class ManyManyList extends RelationList { class ManyManyList extends RelationList {

View File

@ -2,9 +2,11 @@
/** /**
* A DataList that represents a relation. * A DataList that represents a relation.
*
* Adds the notion of a foreign ID that can be optionally set. * Adds the notion of a foreign ID that can be optionally set.
* *
* @todo Is this additional class really necessary? * @package framework
* @subpackage model
*/ */
abstract class RelationList extends DataList { abstract class RelationList extends DataList {
@ -13,8 +15,10 @@ abstract class RelationList extends DataList {
} }
/** /**
* Returns a copy of this list with the ManyMany relationship linked to the given foreign ID. * Returns a copy of this list with the ManyMany relationship linked to
* @param $id An ID or an array of IDs. * the given foreign ID.
*
* @param int|array $id An ID or an array of IDs.
*/ */
public function forForeignID($id) { public function forForeignID($id) {
// Turn a 1-element array into a simple value // Turn a 1-element array into a simple value
@ -43,7 +47,9 @@ abstract class RelationList extends DataList {
} }
/** /**
* Returns a where clause that filters the members of this relationship to just the related items * Returns a where clause that filters the members of this relationship to
* just the related items.
*
* @param $id (optional) An ID or an array of IDs - if not provided, will use the current ids as per getForeignID * @param $id (optional) An ID or an array of IDs - if not provided, will use the current ids as per getForeignID
*/ */
abstract protected function foreignIDFilter($id = null); abstract protected function foreignIDFilter($id = null);

View File

@ -1,19 +1,23 @@
<?php <?php
/** /**
* An ArrayList that represents an unsaved relation. * An {@link ArrayList} that represents an unsaved relation.
* *
* has_many and many_many relations cannot be saved until after the DataObject they're * has_many and many_many relations cannot be saved until after the DataObject
* on has been written. This List pretends to be a RelationList and stores the related * they're on has been written. This List pretends to be a RelationList and
* objects in memory. * stores the related objects in memory.
* *
* It can store both saved objects (as IDs) or unsaved objects (as instances of * It can store both saved objects (as IDs) or unsaved objects (as instances
* $dataClass). Unsaved objects are then written when the list is saved into an instance * of $dataClass). Unsaved objects are then written when the list is saved
* of RelationList. * into an instance of {@link RelationList}.
* *
* Most methods that alter the list of objects throw LogicExceptions. * Most methods that alter the list of objects throw LogicExceptions.
*
* @package framework
* @subpackage model
*/ */
class UnsavedRelationList extends ArrayList { class UnsavedRelationList extends ArrayList {
/** /**
* The DataObject class name that this relation is on * The DataObject class name that this relation is on
* *

View File

@ -1,15 +1,24 @@
<?php <?php
/** /**
* Format of the Oembed config. Autodiscover allows discovery of all URLs. * Format of the Oembed config. Autodiscover allows discovery of all URLs.
* Endpoint set to true means autodiscovery for this specific provider is allowed
* (even if autodiscovery in general has been disabled).
* *
* Endpoint set to true means autodiscovery for this specific provider is
* allowed (even if autodiscovery in general has been disabled).
*
* <code>
*
* name: Oembed
* ---
* Oembed: * Oembed:
* providers: * providers:
* {pattern}: * 'http://*.youtube.com/watch*':
* {endpoint}/true * 'http://www.youtube.com/oembed/'
* autodiscover: * autodiscover:
* true/false * true
* </code>
*
* @package framework
* @subpackage oembed
*/ */
class Oembed { class Oembed {
@ -178,6 +187,10 @@ class Oembed {
} }
} }
/**
* @package framework
* @subpackage oembed
*/
class Oembed_Result extends ViewableData { class Oembed_Result extends ViewableData {
/** /**
* JSON data fetched from the Oembed URL. * JSON data fetched from the Oembed URL.