/** * Handles saving the updated order of objects. */ public function order($request) { $objects = $this->sourceItems(); $sort = Object::get_static($this->sourceClass, 'default_sort'); $newIDs = $request->postVar('ids'); $sortVals = array_values($objects->map('ID', $sort)); // populate new ID values foreach ($objects as $object) { if (!$object->{$sort}) { $table = $object->class; $query = DB::query("SELECT MAX(\"{$sort}\") + 1 FROM \"{$table}\""); $object->{$sort} = $oldIDs[$object->ID] = $query->value(); $object->write(); } } // save the new ID values - but only use existing sort values to prevent // conflicts with items not in the table foreach ($newIDs as $key => $id) { $object = $objects->find('ID', $id); $object->{$sort} = $sortVals[$key]; $object->write(); } $objects->sort($sort); return $this->FieldHolder(); }
/** * @param SiteTree $record * @return Array template data */ static function get_for_record($record) { $items = ''; $message = ''; $navItemClasses = ClassInfo::subclassesFor('SilverStripeNavigatorItem'); array_shift($navItemClasses); // Sort menu items according to priority $menuPriority = array(); $i = 0; foreach ($navItemClasses as $navItemClass) { if ($navItemClass == 'SilverStripeNavigatorItem') { continue; } $i++; $obj = new $navItemClass(); // This funny litle formula ensures that the first item added with the same priority will be left-most. $priority = Object::get_static($navItemClass, 'priority'); $menuPriority[$priority * 100 - 1] = $obj; } ksort($menuPriority); foreach ($menuPriority as $obj) { $text = $obj->getHTML($record); if ($text) { $items .= $text; } $newMessage = $obj->getMessage($record); if ($newMessage) { $message = $newMessage; } } return array('items' => $items, 'message' => $message); }
/** * Alter file path to generated a static (static) error page file to handle error page template on different sub-sites * * @see Error::get_filepath_for_errorcode() * * FIXME since {@link Subsite::currentSubsite()} partly relies on Session, viewing other sub-site (including main site) between * opening ErrorPage in the CMS and publish ErrorPage causes static error page to get generated incorrectly. */ function alternateFilepathForErrorcode($statusCode, $locale = null) { $static_filepath = Object::get_static($this->owner->ClassName, 'static_filepath'); $subdomainPart = ""; // Try to get current subsite from session $subsite = Subsite::currentSubsite(false); // since this function is called from Page class before the controller is created, we have to get subsite from domain instead if (!$subsite) { $subsiteID = Subsite::getSubsiteIDForDomain(); if ($subsiteID != 0) { $subsite = DataObject::get_by_id("Subsite", $subsiteID); } else { $subsite = null; } } if ($subsite) { $subdomain = $subsite->domain(); $subdomainPart = "-{$subdomain}"; } if (singleton('SiteTree')->hasExtension('Translatable') && $locale && $locale != Translatable::default_locale()) { $filepath = $static_filepath . "/error-{$statusCode}-{$locale}{$subdomainPart}.html"; } else { $filepath = $static_filepath . "/error-{$statusCode}{$subdomainPart}.html"; } return $filepath; }
public function onAfterInit() { $cssTemplate = Object::get_static('GalleristPageDecorator', 'css_template'); if ((bool)$cssTemplate && $this->owner->hasMethod('data')) { Requirements::customCSS($this->owner->data()->renderWith($cssTemplate)); } Requirements::themedCSS('gallerist'); }
function testErrorPageLocations() { $subsite1 = $this->objFromFixture('Subsite', 'domaintest1'); Subsite::changeSubsite($subsite1->ID); $path = ErrorPage::get_filepath_for_errorcode(500); $static_path = Object::get_static('ErrorPage', 'static_filepath'); $expected_path = $static_path . '/error-500-' . $subsite1->domain() . '.html'; $this->assertEquals($expected_path, $path); }
public function setUp() { parent::setUp(); $this->oldMarkupTemplate = Object::get_static('GalleristPageDecorator', 'markup_template'); Object::add_static_var('GalleristPageDecorator', 'markup_template', 'Gallerist', true); $this->oldGalleristActive = Object::get_static('Page', 'gallerist_active'); Object::add_static_var('Page', 'gallerist_active', true, true); foreach($this->allFixtureIDs('Image') as $fileID) { $file = DataObject::get_by_id('Image', $fileID); copy(BASE_PATH . "/gallerist/images/{$file->Name}", BASE_PATH . "/{$file->Filename}"); } }
/** * Test {@link Object::addStaticVar()} correctly replaces static vars */ public function testAddStaticReplace() { Object::addStaticVars('ObjectStaticTest_Fourth', array('second' => array('test_4')), true); Object::addStaticVars('ObjectStaticTest_Third', array('second' => array('test_3_2'))); $this->assertEquals(Object::get_static('ObjectStaticTest_Fourth', 'second', true), array('test_4')); $this->assertEquals(Object::get_static('ObjectStaticTest_Third', 'second', true), array('test_3_2', 'test_3')); Object::addStaticVars('ObjectStaticTest_Third', array('second' => array('test_3_2')), true); $this->assertEquals(Object::get_static('ObjectStaticTest_Third', 'second', true), array('test_3_2')); Object::add_static_var('ObjectStaticTest_Third', 'fourth', array('test_3_2')); $this->assertEquals(Object::get_static('ObjectStaticTest_Fourth', 'fourth', true), array('test_3_2', 'test_4')); Object::add_static_var('ObjectStaticTest_Third', 'fourth', array('test_3_2'), true); $this->assertEquals(Object::get_static('ObjectStaticTest_Fourth', 'fourth', true), array('test_4', 'test_3_2')); }
public function __construct($controller, $name = null, $sourceClass = null, $fileFieldName = null, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "Created DESC", $sourceJoin = "") { if (!class_exists("SWFUploadField")) { die("<strong>" . _t('DataObjectManager.ERROR', 'Error') . "</strong>: " . _t('FileDataObjectManager.SWFUPLOAD', 'DataObjectManager requires the SWFUpload module.')); } parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin); // Intelligent constructor for fileFieldName $SNG = singleton($this->sourceClass()); if ($fileFieldName === null) { if ($has_ones = $SNG->stat('has_one')) { foreach ($has_ones as $relation => $value) { if (is_subclass_of($value, "File")) { $fileFieldName = $relation; $fileClassName = $value; break; } } } } if (isset($_REQUEST['ctf'][$this->Name()])) { $this->view = $_REQUEST['ctf'][$this->Name()]['view']; } if ($this->sourceClass() == "File" || is_subclass_of($this->sourceClass(), "File")) { $this->hasDataObject = false; $this->fileFieldName = $name; $this->fileClassName = $this->sourceClass(); $this->dataObjectFieldName = null; } else { $this->dataObjectFieldName = $name; $this->fileFieldName = $fileFieldName; $this->fileClassName = $SNG->has_one($this->fileFieldName); if (!$this->fileClassName) { die("<strong>FileDataObjectManager::__construct():</strong>" . _t('FileDataObjectManager.FILERELATION', 'Could not determine file relationship')); } } $this->controllerClassName = $controller->class; if ($key = array_search($this->controllerClassName, $SNG->stat('has_one'))) { $this->controllerFieldName = $key; } else { $this->controllerFieldName = $this->controllerClassName; } $this->controllerID = $controller->ID; // Check for allowed file types if ($types = Object::get_static($this->fileClassName, 'allowed_file_types')) { $this->setAllowedFileTypes($types); } }
/** * Factory that returns a RESTFormatter subclass that formats in a particular format based on mimetype or extension * * @static * @param SS_HTTPRequest | string - $request * @return RESTFormatter - an instance of a RESTFormatter that can do the job, or null if none can. */ public static function get_formatter($request = null) { // Request can be an SS_HTTPRequest object if ($request instanceof SS_HTTPRequest) { // Try and get the mimetype from the request's Accept header $mimetypes = $request->getAcceptMimetypes(); // Alternatively the type might be specified by the client as an extension on the URL $extension = $request->getExtension(); } else { $mimetypes = array($request); $extension = $request; } // Filter out empty items and */* $mimetypes = array_filter($mimetypes, array(__CLASS__, 'useful_mimetype')); // If we didn't get a mimetype _or_ an extension, use the default if (!$mimetypes && !$extension) { $mimetypes = array(self::$default); } // Now step through looking for matches on any specified mimetype or exception $byMimeType = null; $byExtension = null; foreach (ClassInfo::subclassesFor(__CLASS__) as $class) { if ($class == __CLASS__) { continue; } if ($mimetypes && count(array_intersect($mimetypes, Object::get_static($class, 'mimetypes')))) { $byMimeType = $class; break; // Mimetypes take priority over extensions. If we get a match we're done. } if ($extension && in_array($extension, Object::get_static($class, 'url_extensions'))) { $byExtension = $class; if (!$mimetypes) { break; } // We're only done on a match if we don't have a mimetype to look for. } } // Mime type match gets priority over extension if ($byMimeType) { return new $byMimeType(); } if ($byExtension) { return new $byExtension(); } }
/** * Add the appropriate Director rules for the given controller. */ protected static function add_director_rule_for_controller($controllerClass) { $urlBase = Object::get_static($controllerClass, 'url_base'); $urlSegment = Object::get_static($controllerClass, 'url_segment'); $urlRule = Object::get_static($controllerClass, 'url_rule'); $urlPriority = Object::get_static($controllerClass, 'url_priority'); if ($urlSegment || $controllerClass == "CMSMain") { $link = Controller::join_links($urlBase, $urlSegment) . '/'; // Make director rule if ($urlRule[0] == '/') { $urlRule = substr($urlRule, 1); } $rule = $link . '/' . $urlRule; // the / will combine with the / on the end of $link to make a // Director::addRules($urlPriority, array($rule => $controllerClass)); } }
/** * Factory that returns a RESTParser subclass that parses data in a particular format based on mimetype or content * * TODO: This is pretty copy-pasta from RESTFormatter. Maybe consolidate this code with that? * * @static * @param SS_HTTPRequest | string - $request * @return RESTParser - an instance of a RESTParser that can do the job, or null if none can. */ public static function get_parser($request = null) { // Request can be an SS_HTTPRequest object if ($request instanceof SS_HTTPRequest) { // Try and get the mimetype from the request's Accept header $mimetypes = self::get_content_type_mimetypes($request); // Alternatively the type might be auto-detected from the request $body = $request->getBody(); } else { $mimetypes = array($request); $body = ''; } // Filter out empty items and */* $mimetypes = array_filter($mimetypes, array(__CLASS__, 'useful_mimetype')); // Now step through looking for matches on any specified mimetype or exception $byMimeType = null; $bySignature = null; foreach (ClassInfo::subclassesFor(__CLASS__) as $class) { if ($class == __CLASS__) { continue; } if ($mimetypes && count(array_intersect($mimetypes, Object::get_static($class, 'mimetypes')))) { $byMimeType = $class; break; // Mimetypes take priority over extensions. If we get a match we're done. } if ($body && call_user_func(array($class, 'matches_signature'), $body)) { $bySignature = $class; if (!$mimetypes) { break; } // We're only done on a match if we don't have a mimetype to look for. } } // Mime type match gets priority over extension if ($byMimeType) { return new $byMimeType(); } if ($bySignature) { return new $bySignature(); } }
/** * Debug helper method. * Can be called from /shoppingcart/debug/ * @return String */ public function debug() { $this->calculateOrderAttributes(true); $html = "\r\n\t\t\t<h2>" . $this->ClassName . "</h2><ul>"; $fields = Object::get_static($this->ClassName, "db"); foreach ($fields as $key => $type) { $html .= "<li><b>{$key} ({$type}):</b> " . $this->{$key} . "</li>"; } $fields = Object::get_static($this->ClassName, "casting"); foreach ($fields as $key => $type) { $method = "get" . $key; $html .= "<li><b>{$key} ({$type}):</b> " . $this->{$method}() . " </li>"; } $html .= "</ul>"; return $html; }
/** * Start the MultiForm instance. * * @param Controller instance $controller Controller this form is created on * @param string $name The form name, typically the same as the method name */ public function __construct($controller, $name) { if (isset($_GET['MultiFormSessionID'])) { $this->setCurrentSessionHash($_GET['MultiFormSessionID']); } // Set up the session for this MultiForm instance $this->setSession(); // Get the current step available (Note: either returns an existing // step or creates a new one if none available) $currentStep = $this->getCurrentStep(); // Set the step returned above as the current step $this->setCurrentStep($currentStep); // Set the form of the step to this form instance $currentStep->setForm($this); // Set up the fields for the current step $fields = $currentStep->getFields(); // Set up the actions for the current step $actions = $this->actionsFor($currentStep); // Set up validation (if necessary) $validator = null; $applyValidation = true; // Check if the $_REQUEST action that user clicked is an exempt one $actionNames = Object::get_static(get_class($this), 'actions_exempt_from_validation'); if ($actionNames) { foreach ($actionNames as $exemptAction) { if (!empty($_REQUEST[$exemptAction])) { $applyValidation = false; break; } } } // Apply validation if the current step requires validation (is not exempt) if ($applyValidation) { if ($currentStep->getValidator()) { $validator = $currentStep->getValidator(); } } // Give the fields, actions, and validation for the current step back to the parent Form class parent::__construct($controller, $name, $fields, $actions, $validator); // Set a hidden field in our form with an encrypted hash to identify this session. $this->fields->push(new HiddenField('MultiFormSessionID', false, $this->session->Hash)); // If there is saved data for the current step, we load it into the form it here //(CAUTION: loadData() MUST unserialize first!) if ($currentStep->loadData()) { $this->loadDataFrom($currentStep->loadData()); } // Disable security token - we tie a form to a session ID instead $this->disableSecurityToken(); }
function augmentDatabase() { $classTable = $this->owner->class; $isRootClass = $this->owner->class == ClassInfo::baseDataClass($this->owner->class); // Build a list of suffixes whose tables need versioning $allSuffixes = array(); foreach (Versioned::$versionableExtensions as $versionableExtension => $suffixes) { if ($this->owner->hasExtension($versionableExtension)) { $allSuffixes = array_merge($allSuffixes, (array) $suffixes); foreach ((array) $suffixes as $suffix) { $allSuffixes[$suffix] = $versionableExtension; } } } // Add the default table with an empty suffix to the list (table name = class name) array_push($allSuffixes, ''); foreach ($allSuffixes as $key => $suffix) { // check that this is a valid suffix if (!is_int($key)) { continue; } if ($suffix) { $table = "{$classTable}_{$suffix}"; } else { $table = $classTable; } if ($fields = DataObject::database_fields($this->owner->class)) { $options = Object::get_static($this->owner->class, 'create_table_options'); $indexes = $this->owner->databaseIndexes(); if ($suffix && ($ext = $this->owner->getExtensionInstance($allSuffixes[$suffix]))) { if (!$ext->isVersionedTable($table)) { continue; } $ext->setOwner($this->owner); $fields = $ext->fieldsInExtraTables($suffix); $ext->clearOwner(); $indexes = $fields['indexes']; $fields = $fields['db']; } // Create tables for other stages foreach ($this->stages as $stage) { // Extra tables for _Live, etc. //Change unique indexes to 'index'. Versioned tables may run into unique indexing difficulties otherwise. foreach ($indexes as $key => $index) { if (is_array($index) && $index['type'] == 'unique') { $indexes[$key]['type'] = 'index'; } } if ($stage != $this->defaultStage) { DB::requireTable("{$table}_{$stage}", $fields, $indexes, false, $options); } // Version fields on each root table (including Stage) /* if($isRootClass) { $stageTable = ($stage == $this->defaultStage) ? $table : "{$table}_$stage"; $parts=Array('datatype'=>'int', 'precision'=>11, 'null'=>'not null', 'default'=>(int)0); $values=Array('type'=>'int', 'parts'=>$parts); DB::requireField($stageTable, 'Version', $values); } */ } if ($isRootClass) { // Create table for all versions $versionFields = array_merge(self::$db_for_versions_table, (array) $fields); $versionIndexes = array_merge(self::$indexes_for_versions_table, (array) $indexes); } else { // Create fields for any tables of subclasses $versionFields = array_merge(array("RecordID" => "Int", "Version" => "Int"), (array) $fields); //Unique indexes will not work on versioned tables, so we'll convert them to standard indexes: foreach ($indexes as $key => $index) { if (is_array($index) && strtolower($index['type']) == 'unique') { $indexes[$key]['type'] = 'index'; } } $versionIndexes = array_merge(array('RecordID_Version' => array('type' => 'unique', 'value' => 'RecordID,Version'), 'RecordID' => true, 'Version' => true), (array) $indexes); } if (DB::getConn()->hasTable("{$table}_versions")) { // Fix data that lacks the uniqueness constraint (since this was added later and // bugs meant that the constraint was validated) $duplications = DB::query("SELECT MIN(\"ID\") AS \"ID\", \"RecordID\", \"Version\" \n\t\t\t\t\t\tFROM \"{$table}_versions\" GROUP BY \"RecordID\", \"Version\" \n\t\t\t\t\t\tHAVING COUNT(*) > 1"); foreach ($duplications as $dup) { DB::alteration_message("Removing {$table}_versions duplicate data for " . "{$dup['RecordID']}/{$dup['Version']}", "deleted"); DB::query("DELETE FROM \"{$table}_versions\" WHERE \"RecordID\" = {$dup['RecordID']}\n\t\t\t\t\t\t\tAND \"Version\" = {$dup['Version']} AND \"ID\" != {$dup['ID']}"); } // Remove junk which has no data in parent classes. Only needs to run the following // when versioned data is spread over multiple tables if (!$isRootClass && ($versionedTables = ClassInfo::dataClassesFor($table))) { foreach ($versionedTables as $child) { if ($table == $child) { break; } // only need subclasses $count = DB::query("\n\t\t\t\t\t\t\t\tSELECT COUNT(*) FROM \"{$table}_versions\"\n\t\t\t\t\t\t\t\tLEFT JOIN \"{$child}_versions\" \n\t\t\t\t\t\t\t\t\tON \"{$child}_versions\".\"RecordID\" = \"{$table}_versions\".\"RecordID\"\n\t\t\t\t\t\t\t\t\tAND \"{$child}_versions\".\"Version\" = \"{$table}_versions\".\"Version\"\n\t\t\t\t\t\t\t\tWHERE \"{$child}_versions\".\"ID\" IS NULL\n\t\t\t\t\t\t\t")->value(); if ($count > 0) { DB::alteration_message("Removing orphaned versioned records", "deleted"); $effectedIDs = DB::query("\n\t\t\t\t\t\t\t\t\tSELECT \"{$table}_versions\".\"ID\" FROM \"{$table}_versions\"\n\t\t\t\t\t\t\t\t\tLEFT JOIN \"{$child}_versions\" \n\t\t\t\t\t\t\t\t\t\tON \"{$child}_versions\".\"RecordID\" = \"{$table}_versions\".\"RecordID\"\n\t\t\t\t\t\t\t\t\t\tAND \"{$child}_versions\".\"Version\" = \"{$table}_versions\".\"Version\"\n\t\t\t\t\t\t\t\t\tWHERE \"{$child}_versions\".\"ID\" IS NULL\n\t\t\t\t\t\t\t\t")->column(); if (is_array($effectedIDs)) { foreach ($effectedIDs as $key => $value) { DB::query("DELETE FROM \"{$table}_versions\" WHERE \"{$table}_versions\".\"ID\" = '{$value}'"); } } } } } } DB::requireTable("{$table}_versions", $versionFields, $versionIndexes, true, $options); } else { DB::dontRequireTable("{$table}_versions"); foreach ($this->stages as $stage) { if ($stage != $this->defaultStage) { DB::dontrequireTable("{$table}_{$stage}"); } } } } }
/** * Builds the XML data. * * SilvercartPaymentMethod relations get treated specially here. * * @param DataObject $obj Object to build XML data for * @param array $fields Fields to build XML data for * @param array $relations Relations to support * * @return string * * @author Sebastian Diel <*****@*****.**> * @since 23.06.2014 */ public function convertDataObjectWithoutHeader(DataObject $obj, $fields = null, $relations = null) { $className = $obj->class; $id = $obj->ID; $objHref = Director::absoluteURL(static::$api_base . $obj->class . "/" . $obj->ID); if (substr($obj->ClassName, 0, 17) == 'SilvercartPayment') { $relClassName = 'SilvercartPaymentMethod'; } else { $relClassName = $obj->ClassName; } $xml = "<{$relClassName} href=\"{$objHref}.xml\">\n"; $this->getDataObjectFieldPermissions($obj); $fields = array_intersect((array) $this->getCustomAddFields(), (array) $this->getCustomFields()); foreach ($this->getFieldsForObj($obj) as $fieldName => $fieldType) { // Field filtering if (SilvercartRestfulServer::isBlackListField($obj->class, $fieldName)) { continue; } if ($fields && !in_array($fieldName, $fields)) { continue; } $fieldValue = $obj->{$fieldName}; if (!mb_check_encoding($fieldValue, 'utf-8')) { $fieldValue = "(data is badly encoded)"; } if (is_object($fieldValue) && is_subclass_of($fieldValue, 'Object') && $fieldValue->hasMethod('toXML')) { $xml .= $fieldValue->toXML(); } else { $xml .= "<{$fieldName}>" . Convert::raw2xml($fieldValue) . "</{$fieldName}>\n"; } } if ($this->getRelationDepth() > 0) { foreach ($obj->has_one() as $relName => $relClass) { if ($this->skipRelation($relName, $relClass, $fields)) { continue; } $fieldName = $relName . 'ID'; $href = ''; if ($obj->{$fieldName}) { $relObj = null; if ($this->getRelationDetailDepth() > 0) { $relObj = DataObject::get_by_id($relClass, $obj->{$fieldName}); } if ($relObj) { $relationDepth = $this->getRelationDepth(); $this->setRelationDepth($relationDepth - 1); $originalCustomAddFields = $this->getCustomAddFields(); $customAddFields = Object::get_static($relObj->ClassName, 'custom_add_export_fields'); $this->setCustomAddFields((array) $customAddFields); $xml .= $this->convertDataObjectWithoutHeader($relObj, $fields); $this->setCustomAddFields($originalCustomAddFields); $this->setRelationDepth($relationDepth); } else { $href = Director::absoluteURL(static::$api_base . "{$relClass}/" . $obj->{$fieldName}); } } else { $href = Director::absoluteURL(static::$api_base . "{$className}/{$id}/{$relName}"); } if (!empty($href)) { $xml .= "<{$relName} linktype=\"has_one\" href=\"{$href}.xml\" id=\"" . $obj->{$fieldName} . "\"></{$relName}>\n"; } } foreach ($obj->has_many() as $relName => $relClass) { if ($this->skipRelation($relName, $relClass, $fields)) { continue; } $xml .= $this->addMany($relName, $relClass, $objHref, $obj, 'has_many', $fields); } foreach ($obj->many_many() as $relName => $relClass) { if ($this->skipRelation($relName, $relClass, $fields)) { continue; } $xml .= $this->addMany($relName, $relClass, $objHref, $obj, 'many_many', $fields); } } $xml .= "</{$relClassName}>\n"; return $xml; }
/** * Perform retroactive DataObject cleaning. * * @param SS_HTTPRequest $request */ public function run($request) { if (!Object::get_static('SapphireTest', 'is_running_test')) { JanitorDebug::set_verbose(true); } if (JanitorDBP::available()) { $this->backupPath = JanitorDBP::backup_database(); } $dataObjectSubClasses = (array)ClassInfo::subclassesFor('DataObject'); // Remove DataObject array_shift($dataObjectSubClasses); foreach ($dataObjectSubClasses as $class) { $retroactiveCleaner = new DataObjectRetroactiveCleaner($class); $retroactiveCleaner->clean(); } }
/** * Get a unified array of allowed actions on this controller (if such data is available) from both the controller * ancestry and any extensions. * * @return array|null */ public function allowedActions() { $actions = Object::combined_static(get_class($this), 'allowed_actions', 'RequestHandler'); foreach ($this->extension_instances as $extension) { if ($extensionActions = Object::get_static(get_class($extension), 'allowed_actions')) { $actions = array_merge($actions, $extensionActions); } } if ($actions) { // convert all keys and values to lowercase to // allow for easier comparison, unless it is a permission code $actions = array_change_key_case($actions, CASE_LOWER); foreach ($actions as $key => $value) { if (is_numeric($key)) { $actions[$key] = strtolower($value); } } return $actions; } }
/** * Return a DataObjectSet of ArrayData objects containing the following pieces of info * about each batch action: * - Link * - Title * - DoingText */ function batchActionList() { $actions = Object::get_static($this->class, 'batch_actions'); $actionList = new DataObjectSet(); foreach ($actions as $urlSegment => $actionClass) { $actionObj = new $actionClass(); if ($actionObj->canView()) { $actionDef = new ArrayData(array("Link" => Controller::join_links($this->Link(), $urlSegment), "Title" => $actionObj->getActionTitle(), "DoingText" => $actionObj->getDoingText())); $actionList->push($actionDef); } } return $actionList; }
/** * Get the value of a field on this object, automatically inserting the value into any available casting objects * that have been specified. * * @param string $fieldName * @param array $arguments * @param bool $forceReturnedObject if TRUE, the value will ALWAYS be casted to an object before being returned, * even if there is no explicit casting information * @param string $cacheName a custom cache name */ public function obj($fieldName, $arguments = null, $forceReturnedObject = true, $cache = false, $cacheName = null) { if (isset($_REQUEST['debug_profile'])) { Profiler::mark("obj.{$fieldName}", "on a {$this->class} object"); } if (!$cacheName) { $cacheName = $arguments ? $fieldName . implode(',', $arguments) : $fieldName; } if (!isset($this->objCache[$cacheName])) { if ($this->hasMethod($fieldName)) { $value = $arguments ? call_user_func_array(array($this, $fieldName), $arguments) : $this->{$fieldName}(); } else { $value = $this->{$fieldName}; } if (!is_object($value) && ($this->castingClass($fieldName) || $forceReturnedObject)) { if (!($castConstructor = $this->castingHelper($fieldName))) { $castConstructor = $this->stat('default_cast'); } $valueObject = Object::create_from_string($castConstructor, $fieldName); $valueObject->setValue($value, $this->hasMethod('getAllFields') ? $this->getAllFields() : null); $value = $valueObject; } if ($cache) { $this->objCache[$cacheName] = $value; } } else { $value = $this->objCache[$cacheName]; } if (isset($_REQUEST['debug_profile'])) { Profiler::unmark("obj.{$fieldName}", "on a {$this->class} object"); } if (!is_object($value) && $forceReturnedObject) { $default = Object::get_static('ViewableData', 'default_cast'); $value = new $default($fieldName); } return $value; }
/** * Test that DataObject::$api_access can be set to true via a extension */ function testApiAccessCanBeExtended() { $this->assertTrue(Object::get_static('DataExtensionTest_Member', 'api_access')); }
public function getSetting($setting) { if($this->$setting) { return $this->$setting; } return Object::get_static($this->class,DOMUtil::to_underscore($setting)); }
/** * Handles URL requests. * * - ViewableData::handleRequest() iterates through each rule in {@link self::$url_handlers}. * - If the rule matches, the named method will be called. * - If there is still more URL to be processed, then handleRequest() is called on the object that that method returns. * * Once all of the URL has been processed, the final result is returned. However, if the final result is an array, this * array is interpreted as being additional template data to customise the 2nd to last result with, rather than an object * in its own right. This is most frequently used when a Controller's action will return an array of data with which to * customise the controller. * * @param $params The parameters taken from the parsed URL of the parent url handler * @param $request The {@link HTTPRequest} object that is reponsible for distributing URL parsing * @uses HTTPRequest * @uses HTTPRequest->match() * @return HTTPResponse|RequestHandler|string|array */ function handleRequest($request) { // $handlerClass is used to step up the class hierarchy to implement url_handlers inheritance $handlerClass = $this->class ? $this->class : get_class($this); if ($this->brokenOnConstruct) { user_error("parent::__construct() needs to be called on {$handlerClass}::__construct()", E_USER_WARNING); } $this->request = $request; // We stop after RequestHandler; in other words, at ViewableData while ($handlerClass && $handlerClass != 'ViewableData') { $urlHandlers = Object::get_static($handlerClass, 'url_handlers'); if ($urlHandlers) { foreach ($urlHandlers as $rule => $action) { if (isset($_REQUEST['debug_request'])) { Debug::message("Testing '{$rule}' with '" . $request->remaining() . "' on {$this->class}"); } if ($params = $request->match($rule, true)) { // FIXME: This unnecessary coupling was added to fix a bug in Image_Uploader. if ($this instanceof Controller) { $this->urlParams = $request->allParams(); } if (isset($_REQUEST['debug_request'])) { Debug::message("Rule '{$rule}' matched to action '{$action}' on {$this->class}. Latest request params: " . var_export($request->latestParams(), true)); } // Actions can reference URL parameters, eg, '$Action/$ID/$OtherID' => '$Action', if ($action[0] == '$') { $action = $params[substr($action, 1)]; } if ($this->checkAccessAction($action)) { if (!$action) { if (isset($_REQUEST['debug_request'])) { Debug::message("Action not set; using default action method name 'index'"); } $action = "index"; } else { if (!is_string($action)) { user_error("Non-string method name: " . var_export($action, true), E_USER_ERROR); } } $result = $this->{$action}($request); } else { return $this->httpError(403, "Action '{$action}' isn't allowed on class {$this->class}"); } if ($result instanceof HTTPResponse && $result->isError()) { if (isset($_REQUEST['debug_request'])) { Debug::message("Rule resulted in HTTP error; breaking"); } return $result; } // If we return a RequestHandler, call handleRequest() on that, even if there is no more URL to parse. // It might have its own handler. However, we only do this if we haven't just parsed an empty rule ourselves, // to prevent infinite loops if (!$request->isEmptyPattern($rule) && is_object($result) && $result instanceof RequestHandler) { $returnValue = $result->handleRequest($request); // Array results can be used to handle if (is_array($returnValue)) { $returnValue = $this->customise($returnValue); } return $returnValue; // If we return some other data, and all the URL is parsed, then return that } else { if ($request->allParsed()) { return $result; // But if we have more content on the URL and we don't know what to do with it, return an error. } else { return $this->httpError(404, "I can't handle sub-URLs of a {$this->class} object."); } } return $this; } } } $handlerClass = get_parent_class($handlerClass); } // If nothing matches, return this object return $this; }
/** * Get all registered actions through the static defaults set by {@link register()}. * Filters for the currently set {@link recordClass}. * * @return array See {@link register()} for the returned format. */ function batchActions() { $actions = Object::get_static($this->class, 'batch_actions'); if ($actions) { foreach ($actions as $action) { if ($action['recordClass'] != $this->recordClass) { unset($action); } } } return $actions; }
function stat($name, $uncached = false) { return Object::get_static($this->class ? $this->class : get_class($this), $name, $uncached); }
function Description() { return Object::get_static($this->class, 'description'); }
/** * Returns a merging of the model's default syncing configuration * and the context configuration for this model * * @param string $model * @return array */ public function getConfig($model) { $default = null; if (class_exists($model)) { if (class_exists('Config')) { $default = Config::inst()->get($model, 'sync'); } else { $default = Object::get_static($model, 'sync'); } } if (!is_array($default)) { $default = array(); } $override = isset($this->modelConfig[$model]) ? $this->modelConfig[$model] : array(); return array_merge($default, $override); }
/** * Test that DataObject::$api_access can be set to true via a decorator */ function testApiAccessCanBeDecorated() { $this->assertTrue(Object::get_static('DataObjectDecoratorTest_Member', 'api_access')); }
function getName() { $stat = Object::get_static($this->noun, 'name'); return $stat ? $stat : $this->noun; }
/** * Get an object from the fixture. * @param $className The data class, as specified in your fixture file. Parent classes won't work * @param $identifier The identifier string, as provided in your fixture file */ protected function objFromFixture($className, $identifier) { if (!$this->fixtures) { user_error("You've called objFromFixture() but you haven't specified static \$fixture_file.\n", E_USER_WARNING); return; } foreach ($this->fixtures as $fixture) { $match = $fixture->objFromFixture($className, $identifier); if ($match) { return $match; } } $fixtureFiles = Object::get_static(get_class($this), 'fixture_file'); user_error(sprintf("Couldn't find object '%s' (class: %s) in files %s", $identifier, $className, is_array($fixtureFiles) ? implode(',', $fixtureFiles) : $fixtureFiles), E_USER_ERROR); return false; }
public function Gallerist() { if (Object::get_static($this->owner->class, 'gallerist_active')) { return $this->owner->renderWith(Object::get_static('GalleristPageDecorator', 'markup_template')); } return ''; }