Example #1
0
 /**
  * The list of TodoLists
  *
  * @param SS_List $lists
  * @return $this
  */
 public function setLists($lists)
 {
     $this->lists = $lists->filterByCallback(function ($item) {
         return $item->canView();
     });
     return $this;
 }
 /**
  * Generate a {@link PHPExcel} for the provided DataObject List
  * @param  SS_List $set List of DataObjects
  * @return PHPExcel
  */
 public function getPhpExcelObject(SS_List $set)
 {
     // Get the first object. We'll need it to know what type of objects we
     // are dealing with
     $first = $set->first();
     // Get the Excel object
     $excel = $this->setupExcel($first);
     $sheet = $excel->setActiveSheetIndex(0);
     // Make sure we have at lease on item. If we don't, we'll be returning
     // an empty spreadsheet.
     if ($first) {
         // Set up the header row
         $fields = $this->getFieldsForObj($first);
         $this->headerRow($sheet, $fields);
         // Add a new row for each DataObject
         foreach ($set as $item) {
             $this->addRow($sheet, $item, $fields);
         }
         // Freezing the first column and the header row
         $sheet->freezePane("B2");
         // Auto sizing all the columns
         $col = sizeof($fields);
         for ($i = 0; $i < $col; $i++) {
             $sheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true);
         }
     }
     return $excel;
 }
Example #3
0
	/**
	 * Helper method for processing batch actions.
	 * Returns a set of status-updating JavaScript to return to the CMS.
	 *
	 * @param $objs The SS_List of objects to perform this batch action
	 * on.
	 * @param $helperMethod The method to call on each of those objects.
	 * @return JSON encoded map in the following format:
	 *  {
	 *     'modified': {
	 *       3: {'TreeTitle': 'Page3'},
	 *       5: {'TreeTitle': 'Page5'}
	 *     },
	 *     'deleted': {
	 *       // all deleted pages
	 *     }
	 *  }
	 */
	public function batchaction(SS_List $objs, $helperMethod, $successMessage, $arguments = array()) {
		$status = array('modified' => array(), 'error' => array());
		
		foreach($objs as $obj) {
			
			// Perform the action
			if (!call_user_func_array(array($obj, $helperMethod), $arguments)) {
				$status['error'][$obj->ID] = '';
			}
			
			// Now make sure the tree title is appropriately updated
			$publishedRecord = DataObject::get_by_id($this->managedClass, $obj->ID);
			if ($publishedRecord) {
				$status['modified'][$publishedRecord->ID] = array(
					'TreeTitle' => $publishedRecord->TreeTitle,
				);
			}
			$obj->destroy();
			unset($obj);
		}

		$response = Controller::curr()->getResponse();
		if($response) {
			$response->setStatusCode(
				200, 
				sprintf($successMessage, $objs->Count(), count($status['error']))
			);
		}

		return Convert::raw2json($status);
	}
 /**
  * {@inheritdoc}
  */
 public function getColumnContent($gridField, $record, $columnName)
 {
     if ($columnName === 'MergeAction' && $record->{$this->childMethod}()->Count() > 0) {
         $dropdown = new DropdownField('Target', 'Target', $this->records->exclude('ID', $record->ID)->map());
         $prefix = strtolower($this->parentMethod . '-' . $this->childMethod);
         $action = GridFieldFormAction::create($gridField, 'MergeAction' . $record->ID, 'Move', 'merge', array('record' => $record->ID, 'target' => $prefix . '-target-record-' . $record->ID));
         $action->setExtraAttributes(array('data-target' => $prefix . '-target-record-' . $record->ID));
         return $dropdown->Field() . $action->Field() . '<a title="Move posts to" class="MergeActionReveal">move posts to</a>';
     }
     return null;
 }
 /**
  * @param SS_List $scope the scope to iterate over - handy if you don't want
  * to add this extension for a one-off use
  * @return array
  */
 public static function to_autocomplete_array($scope)
 {
     $items = $scope->toArray();
     foreach ($items as &$item) {
         if ($item->hasMethod('toAutocompleteMap')) {
             $item = $item->toAutocompleteMap();
         } else {
             $item = $item->toMap();
         }
     }
     return $items;
 }
 /**
  * Usage [e.g. in getCMSFields]
  *    $field = new PickerField('Authors', 'Selected Authors', $this->Authors(), 'Select Author(s)');
  *     
  * @param string $name              - Name of field (typically the relationship method)
  * @param string $title             - GridField Title
  * @param SS_List $dataList         - Result of the relationship component method (E.g. $this->Authors())
  * @param string $linkExistingTitle - AddExisting Button Title
  * @param string $sortField         - Field to sort on. Be sure it exists in the $many_many_extraFields static
  */
 public function __construct($name, $title = null, SS_List $dataList = null, $linkExistingTitle = null, $sortField = null)
 {
     $config = GridfieldConfig::create()->addComponents(new GridFieldButtonRow('before'), new GridFieldToolbarHeader(), new GridFieldDataColumns(), new GridFieldTitleHeader(), new GridFieldPaginator(), new PickerFieldAddExistingSearchButton(), new PickerFieldDeleteAction());
     if ($sortField) {
         $config->addComponent(new GridFieldOrderableRows($sortField));
     }
     if (!$linkExistingTitle) {
         $linkExistingTitle = $this->isHaveOne() ? 'Select a ' . $dataList->dataClass() : 'Select ' . $dataList->dataClass() . '(s)';
         // plural [has_many, many_many]
     }
     $config->getComponentByType('PickerFieldAddExistingSearchButton')->setTitle($linkExistingTitle);
     return parent::__construct($name, $title, $dataList, $config);
 }
 /**
  * Adds the records to the database and returns a new {@link DataList}
  *
  * @param GridField
  * @param SS_List
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     $state = $gridField->State->MockDataGenerator;
     $count = (string) $state->Count;
     if (!$count) {
         return $dataList;
     }
     $generator = new MockDataBuilder($gridField->getModelClass());
     $ids = $generator->setCount($count)->setIncludeRelations($state->IncludeRelations)->setDownloadImages($state->DownloadImages === true)->generate();
     foreach ($ids as $id) {
         $dataList->add($id);
     }
     return $dataList;
 }
 /**
  * @param string $name
  * @param string $title
  * @param DataObjectInterface $object
  * @param string $sort
  * @param SS_List $source
  * @param string $titleField
  */
 public function __construct($name, $title, DataObjectInterface $object, $sort = false, SS_List $source = null, $titleField = 'Title')
 {
     $this->setSort($sort);
     if ($object->many_many($name)) {
         $dataSource = $object->{$name}();
         // Check if we're dealing with an UnsavedRelationList
         $unsaved = $dataSource instanceof UnsavedRelationList;
         // Store the relation's class name
         $class = $dataSource->dataClass();
         $this->dataClass = $class;
         // Sort the items
         if ($this->getSort()) {
             $dataSource = $dataSource->sort($this->getSort());
         }
         // If we're dealing with an UnsavedRelationList, it'll be empty, so we
         // can skip this and just use an array of all available items
         if ($unsaved) {
             $dataSource = $class::get()->map()->toArray();
         } else {
             // If we've been given a list source, filter on those IDs only.
             if ($source) {
                 $dataSource = $dataSource->filter('ID', $source->column('ID'));
             }
             // Start building the data source from scratch. Currently selected items first,
             // in the correct sort order
             $dataSource = $dataSource->map('ID', $titleField)->toArray();
             // Get the other items
             $theRest = $class::get();
             // Exclude items that we've already found
             if (!empty($dataSource)) {
                 $theRest = $theRest->exclude('ID', array_keys($dataSource));
             }
             // If we've been given a list source, filter on those IDs only
             if ($source) {
                 $theRest = $theRest->filter('ID', $source->column('ID'));
             }
             $theRest = $theRest->map('ID', $titleField)->toArray();
             // ... we then add the remaining items in whatever order they come
             $dataSource = $dataSource + $theRest;
         }
     } elseif ($source instanceof SS_List) {
         $dataSource = $source->map('ID', $titleField)->toArray();
     } elseif (is_array($source) && ArrayLib::is_associative($source)) {
         $dataSource = $source;
     } else {
         user_error('MultiSelectField::__construct(): MultiSelectField only supports many-to-many relations');
     }
     parent::__construct($name, $title, $dataSource, '', null, true);
 }
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     if (!$gridField->State->GridFieldAddRelation) {
         return $dataList;
     }
     $objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
     if ($objectID) {
         $object = DataObject::get_by_id($dataList->dataclass(), $objectID);
         if ($object) {
             $dataList->add($object);
         }
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
 /**
  * Get the list of extra data from the $record as saved into it by
  * {@see Form::saveInto()}
  *
  * Handles detection of falsey values explicitly saved into the
  * DataObject by formfields
  *
  * @param DataObject $record
  * @param SS_List $list
  * @return array List of data to write to the relation
  */
 protected function getExtraSavedData($record, $list)
 {
     // Skip extra data if not ManyManyList
     if (!$list instanceof ManyManyList) {
         return null;
     }
     $data = array();
     foreach ($list->getExtraFields() as $field => $dbSpec) {
         $savedField = "ManyMany[{$field}]";
         if ($record->hasField($savedField)) {
             $data[$field] = $record->getField($savedField);
         }
     }
     return $data;
 }
Example #11
0
 public function run(SS_List $pages)
 {
     // Sort pages by depth
     $pageArray = $pages->toArray();
     // because of https://bugs.php.net/bug.php?id=50688
     foreach ($pageArray as $page) {
         $page->getPageLevel();
     }
     usort($pageArray, function ($a, $b) {
         return $a->getPageLevel() - $b->getPageLevel();
     });
     $pages = new ArrayList($pageArray);
     // Restore
     return $this->batchaction($pages, 'doRestoreToStage', _t('CMSBatchActions.RESTORED_PAGES', 'Restored %d pages'));
 }
Example #12
0
 /**
  * @return SS_List
  */
 public function getItems()
 {
     $name = $this->getName();
     if (!$this->items || !$this->items->exists()) {
         $record = $this->getRecord();
         $this->items = array();
         // Try to auto-detect relationship
         if ($record && $record->exists()) {
             if ($record->has_many($name) || $record->many_many($name)) {
                 // Ensure relationship is cast to an array, as we can't alter the items of a DataList/RelationList (see below)
                 $this->items = $record->{$name}()->toArray();
             } elseif ($record->has_one($name)) {
                 $item = $record->{$name}();
                 if ($item && $item->exists()) {
                     $this->items = array($record->{$name}());
                 }
             }
         }
         $this->items = new ArrayList($this->items);
         // hack to provide $UploadFieldThumbnailURL, $hasRelation and $UploadFieldEditLink in template for each file
         if ($this->items->exists()) {
             foreach ($this->items as $i => $file) {
                 $this->items[$i] = $this->customiseFile($file);
                 if (!$file->canView()) {
                     unset($this->items[$i]);
                 }
                 // Respect model permissions
             }
         }
     }
     return $this->items;
 }
 /**
  * If an object ID is set, add the object to the list
  *
  * @param GridField $gridField
  * @param SS_List $dataList
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     if (!$gridField->State->GridFieldAddRelation) {
         return $dataList;
     }
     $objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
     if ($objectID) {
         $object = DataObject::get_by_id($dataList->dataclass(), $objectID);
         if ($object) {
             $virtual = new ElementVirtualLinked();
             $virtual->LinkedElementID = $object->ID;
             $virtual->write();
             $dataList->add($virtual);
         }
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
 /**
  * Takes a list of groups and members and return a list of unique member.
  *
  * @param SS_List $groups
  * @param SS_List $members
  *
  * @return ArrayList
  */
 public static function merge_owners(SS_List $groups, SS_List $members)
 {
     $contentReviewOwners = new ArrayList();
     if ($groups->count()) {
         $groupIDs = array();
         foreach ($groups as $group) {
             $familyIDs = $group->collateFamilyIDs();
             if (is_array($familyIDs)) {
                 $groupIDs = array_merge($groupIDs, array_values($familyIDs));
             }
         }
         array_unique($groupIDs);
         if (count($groupIDs)) {
             $groupMembers = DataObject::get("Member")->where("\"Group\".\"ID\" IN (" . implode(",", $groupIDs) . ")")->leftJoin("Group_Members", "\"Member\".\"ID\" = \"Group_Members\".\"MemberID\"")->leftJoin("Group", "\"Group_Members\".\"GroupID\" = \"Group\".\"ID\"");
             $contentReviewOwners->merge($groupMembers);
         }
     }
     $contentReviewOwners->merge($members);
     $contentReviewOwners->removeDuplicates();
     return $contentReviewOwners;
 }
Example #15
0
 /**
  * Returns a data class that is a DataObject type that this GridField should look like.
  *
  * @return string
  *
  * @throws LogicException
  */
 public function getModelClass()
 {
     if ($this->modelClassName) {
         return $this->modelClassName;
     }
     if ($this->list && method_exists($this->list, 'dataClass')) {
         $class = $this->list->dataClass();
         if ($class) {
             return $class;
         }
     }
     throw new LogicException('GridField doesn\'t have a modelClassName, so it doesn\'t know the columns of this grid.');
 }
 /**
  * If an object ID is set, add the object to the list
  *
  * @param GridField $gridField
  * @param SS_List $dataList
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     if (!$gridField->State->GridFieldAddRelation) {
         return $dataList;
     }
     $objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
     if ($objectID) {
         $object = DataObject::get_by_id($dataList->dataclass(), $objectID);
         if ($object) {
             if ($this->_item_limit > 0 && $dataList->count() + 1 > $this->_item_limit) {
                 $gridField->getForm()->getController()->getResponse()->addHeader('X-Status', _t('LimitedRelationsGridField.ITEM_LIMIT_REACHED', '_You cannot add any more items, you can only add {count} items. Please remove one then try again.', array('count' => $this->_item_limit)));
             } else {
                 $dataList->add($object);
             }
         }
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
 /**
  * If an object ID is set, add the object to the list
  *
  * @param GridField $gridField
  * @param SS_List $dataList
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     if (!$gridField->State->GridFieldAddRelation) {
         return $dataList;
     }
     $objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
     if ($objectID) {
         $object = DataObject::get_by_id($dataList->dataclass(), $objectID);
         if ($object) {
             // if the object is currently not linked to either a page or another list then we want to link to
             // the original, otherwise link to a clone
             if (!$object->ParentID && !$object->ListID) {
                 $dataList->add($object);
             } else {
                 $virtual = new ElementVirtualLinked();
                 $virtual->LinkedElementID = $object->ID;
                 $virtual->write();
                 $dataList->add($virtual);
             }
         }
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
Example #18
0
 /**
  * Loads the related record values into this field. UploadField can be uploaded
  * in one of three ways:
  * 
  *  - By passing in a list of file IDs in the $value parameter (an array with a single
  *    key 'Files', with the value being the actual array of IDs).
  *  - By passing in an explicit list of File objects in the $record parameter, and
  *    leaving $value blank.
  *  - By passing in a dataobject in the $record parameter, from which file objects
  *    will be extracting using the field name as the relation field.
  * 
  * Each of these methods will update both the items (list of File objects) and the 
  * field value (list of file ID values).
  * 
  * @param array $value Array of submitted form data, if submitting from a form
  * @param array|DataObject|SS_List $record Full source record, either as a DataObject,
  * SS_List of items, or an array of submitted form data
  * @return UploadField Self reference
  */
 public function setValue($value, $record = null)
 {
     // If we're not passed a value directly, we can attempt to infer the field
     // value from the second parameter by inspecting its relations
     $items = new ArrayList();
     // Determine format of presented data
     if (empty($value) && $record) {
         // If a record is given as a second parameter, but no submitted values,
         // then we should inspect this instead for the form values
         if ($record instanceof DataObject && $record->hasMethod($this->getName())) {
             // If given a dataobject use reflection to extract details
             $data = $record->{$this->getName()}();
             if ($data instanceof DataObject) {
                 // If has_one, add sole item to default list
                 $items->push($data);
             } elseif ($data instanceof SS_List) {
                 // For many_many and has_many relations we can use the relation list directly
                 $items = $data;
             }
         } elseif ($record instanceof SS_List) {
             // If directly passing a list then save the items directly
             $items = $record;
         }
     } elseif (!empty($value['Files'])) {
         // If value is given as an array (such as a posted form), extract File IDs from this
         $class = $this->getRelationAutosetClass();
         $items = DataObject::get($class)->byIDs($value['Files']);
     }
     // If javascript is disabled, direct file upload (non-html5 style) can
     // trigger a single or multiple file submission. Note that this may be
     // included in addition to re-submitted File IDs as above, so these
     // should be added to the list instead of operated on independently.
     if ($uploadedFiles = $this->extractUploadedFileData($value)) {
         foreach ($uploadedFiles as $tempFile) {
             $file = $this->saveTemporaryFile($tempFile, $error);
             if ($file) {
                 $items->add($file);
             } else {
                 throw new ValidationException($error);
             }
         }
     }
     // Filter items by what's allowed to be viewed
     $filteredItems = new ArrayList();
     $fileIDs = array();
     foreach ($items as $file) {
         if ($file->exists() && $file->canView()) {
             $filteredItems->push($file);
             $fileIDs[] = $file->ID;
         }
     }
     // Filter and cache updated item list
     $this->items = $filteredItems;
     // Same format as posted form values for this field. Also ensures that
     // $this->setValue($this->getValue()); is non-destructive
     $value = $fileIDs ? array('Files' => $fileIDs) : null;
     // Set value using parent
     return parent::setValue($value, $record);
 }
 public function Field($properties = array())
 {
     Requirements::css(FRAMEWORK_DIR . '/css/CheckboxSetField.css');
     Requirements::javascript(FRAMEWORK_DIR . '/javascript/PermissionCheckboxSetField.js');
     $uninheritedCodes = array();
     $inheritedCodes = array();
     $records = $this->records ? $this->records : new ArrayList();
     // Get existing values from the form record (assuming the formfield name is a join field on the record)
     if (is_object($this->form)) {
         $record = $this->form->getRecord();
         if ($record && (is_a($record, 'Group') || is_a($record, 'PermissionRole')) && !$records->find('ID', $record->ID)) {
             $records->push($record);
         }
     }
     // Get all 'inherited' codes not directly assigned to the group (which is stored in $values)
     foreach ($records as $record) {
         // Get all uninherited permissions
         $relationMethod = $this->name;
         foreach ($record->{$relationMethod}() as $permission) {
             if (!isset($uninheritedCodes[$permission->Code])) {
                 $uninheritedCodes[$permission->Code] = array();
             }
             $uninheritedCodes[$permission->Code][] = _t('PermissionCheckboxSetField.AssignedTo', 'assigned to "{title}"', array('title' => $record->Title));
         }
         // Special case for Group records (not PermissionRole):
         // Determine inherited assignments
         if (is_a($record, 'Group')) {
             // Get all permissions from roles
             if ($record->Roles()->Count()) {
                 foreach ($record->Roles() as $role) {
                     foreach ($role->Codes() as $code) {
                         if (!isset($inheritedCodes[$code->Code])) {
                             $inheritedCodes[$code->Code] = array();
                         }
                         $inheritedCodes[$code->Code][] = _t('PermissionCheckboxSetField.FromRole', 'inherited from role "{title}"', 'A permission inherited from a certain permission role', array('title' => $role->Title));
                     }
                 }
             }
             // Get from parent groups
             $parentGroups = $record->getAncestors();
             if ($parentGroups) {
                 foreach ($parentGroups as $parent) {
                     if (!$parent->Roles()->Count()) {
                         continue;
                     }
                     foreach ($parent->Roles() as $role) {
                         if ($role->Codes()) {
                             foreach ($role->Codes() as $code) {
                                 if (!isset($inheritedCodes[$code->Code])) {
                                     $inheritedCodes[$code->Code] = array();
                                 }
                                 $inheritedCodes[$code->Code][] = _t('PermissionCheckboxSetField.FromRoleOnGroup', 'inherited from role "%s" on group "%s"', 'A permission inherited from a role on a certain group', array('roletitle' => $role->Title, 'grouptitle' => $parent->Title));
                             }
                         }
                     }
                     if ($parent->Permissions()->Count()) {
                         foreach ($parent->Permissions() as $permission) {
                             if (!isset($inheritedCodes[$permission->Code])) {
                                 $inheritedCodes[$permission->Code] = array();
                             }
                             $inheritedCodes[$permission->Code][] = _t('PermissionCheckboxSetField.FromGroup', 'inherited from group "{title}"', 'A permission inherited from a certain group', array('title' => $parent->Title));
                         }
                     }
                 }
             }
         }
     }
     $odd = 0;
     $options = '';
     $globalHidden = (array) Config::inst()->get('Permission', 'hidden_permissions');
     if ($this->source) {
         $privilegedPermissions = Permission::config()->privileged_permissions;
         // loop through all available categorized permissions and see if they're assigned for the given groups
         foreach ($this->source as $categoryName => $permissions) {
             $options .= "<li><h5>{$categoryName}</h5></li>";
             foreach ($permissions as $code => $permission) {
                 if (in_array($code, $this->hiddenPermissions)) {
                     continue;
                 }
                 if (in_array($code, $globalHidden)) {
                     continue;
                 }
                 $value = $permission['name'];
                 $odd = ($odd + 1) % 2;
                 $extraClass = $odd ? 'odd' : 'even';
                 $extraClass .= ' val' . str_replace(' ', '', $code);
                 $itemID = $this->id() . '_' . preg_replace('/[^a-zA-Z0-9]+/', '', $code);
                 $checked = $disabled = $inheritMessage = '';
                 $checked = isset($uninheritedCodes[$code]) || isset($inheritedCodes[$code]) ? ' checked="checked"' : '';
                 $title = $permission['help'] ? 'title="' . htmlentities($permission['help'], ENT_COMPAT, 'UTF-8') . '" ' : '';
                 if (isset($inheritedCodes[$code])) {
                     // disable inherited codes, as any saving logic would be too complicate to express in this
                     // interface
                     $disabled = ' disabled="true"';
                     $inheritMessage = ' (' . join(', ', $inheritedCodes[$code]) . ')';
                 } elseif ($this->records && $this->records->Count() > 1 && isset($uninheritedCodes[$code])) {
                     // If code assignments are collected from more than one "source group",
                     // show its origin automatically
                     $inheritMessage = ' (' . join(', ', $uninheritedCodes[$code]) . ')';
                 }
                 // Disallow modification of "privileged" permissions unless currently logged-in user is an admin
                 if (!Permission::check('ADMIN') && in_array($code, $privilegedPermissions)) {
                     $disabled = ' disabled="true"';
                 }
                 // If the field is readonly, always mark as "disabled"
                 if ($this->readonly) {
                     $disabled = ' disabled="true"';
                 }
                 $inheritMessage = '<small>' . $inheritMessage . '</small>';
                 $icon = $checked ? 'accept' : 'decline';
                 // If the field is readonly, add a span that will replace the disabled checkbox input
                 if ($this->readonly) {
                     $options .= "<li class=\"{$extraClass}\">" . "<input id=\"{$itemID}\"{$disabled} name=\"{$this->name}[{$code}]\" type=\"checkbox\"" . " value=\"{$code}\"{$checked} class=\"checkbox\" />" . "<label {$title}for=\"{$itemID}\">" . "<span class=\"ui-button-icon-primary ui-icon btn-icon-{$icon}\"></span>" . "{$value}{$inheritMessage}</label>" . "</li>\n";
                 } else {
                     $options .= "<li class=\"{$extraClass}\">" . "<input id=\"{$itemID}\"{$disabled} name=\"{$this->name}[{$code}]\" type=\"checkbox\"" . " value=\"{$code}\"{$checked} class=\"checkbox\" />" . "<label {$title}for=\"{$itemID}\">{$value}{$inheritMessage}</label>" . "</li>\n";
                 }
             }
         }
     }
     if ($this->readonly) {
         return "<ul id=\"{$this->id()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n" . "<li class=\"help\">" . _t('Permissions.UserPermissionsIntro', 'Assigning groups to this user will adjust the permissions they have.' . ' See the groups section for details of permissions on individual groups.') . "</li>" . $options . "</ul>\n";
     } else {
         return "<ul id=\"{$this->id()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n" . $options . "</ul>\n";
     }
 }
 /**
  * Detects and corrects items with a sort column value of 0, by appending them to the bottom of the list
  * @param GridField $gridField Grid Field Reference
  * @param SS_List $dataList Data List of items to be checked
  */
 protected function fixSortColumn($gridField, SS_List $dataList)
 {
     if (class_exists('UnsavedRelationList') && $dataList instanceof UnsavedRelationList) {
         return;
     }
     $list = clone $dataList;
     $list = $list->alterDataQuery(function ($query, SS_List $tmplist) {
         $query->limit(array());
         return $query;
     });
     $many_many = $list instanceof ManyManyList;
     if (!$many_many) {
         $sng = singleton($gridField->getModelClass());
         $fieldType = $sng->db($this->sortColumn);
         if (!$fieldType || !($fieldType == 'Int' || is_subclass_of('Int', $fieldType))) {
             if (is_array($fieldType)) {
                 user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR);
             } else {
                 user_error('Sort column ' . $this->sortColumn . ' must be an Int, column is of type ' . $fieldType, E_USER_ERROR);
             }
             exit;
         }
     }
     $max = $list->Max($this->sortColumn);
     $list = $list->filter($this->sortColumn, 0)->sort("Created,ID");
     if ($list->Count() > 0) {
         $owner = $gridField->Form->getRecord();
         $sortColumn = $this->sortColumn;
         $i = 1;
         if ($many_many) {
             list($parentClass, $componentClass, $parentField, $componentField, $table) = $owner->many_many($gridField->getName());
             $extraFields = $owner->many_many_extraFields($gridField->getName());
             if (!$extraFields || !array_key_exists($this->sortColumn, $extraFields) || !($extraFields[$this->sortColumn] == 'Int' || is_subclass_of('Int', $extraFields[$this->sortColumn]))) {
                 user_error('Sort column ' . $this->sortColumn . ' must be an Int, column is of type ' . $extraFields[$this->sortColumn], E_USER_ERROR);
                 exit;
             }
         } else {
             //Find table containing the sort column
             $table = false;
             $class = $gridField->getModelClass();
             $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED);
             if (!empty($db) && array_key_exists($sortColumn, $db)) {
                 $table = $class;
             } else {
                 $classes = ClassInfo::ancestry($class, true);
                 foreach ($classes as $class) {
                     $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED);
                     if (!empty($db) && array_key_exists($sortColumn, $db)) {
                         $table = $class;
                         break;
                     }
                 }
             }
             if ($table === false) {
                 user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR);
                 exit;
             }
             $baseDataClass = ClassInfo::baseDataClass($gridField->getModelClass());
         }
         //Start transaction if supported
         if (DB::getConn()->supportsTransactions()) {
             DB::getConn()->transactionStart();
         }
         $idCondition = null;
         if ($this->append_to_top && !$list instanceof RelationList) {
             $idCondition = '"ID" IN(\'' . implode("','", $dataList->getIDList()) . '\')';
         }
         if ($this->append_to_top) {
             $topIncremented = array();
         }
         foreach ($list as $obj) {
             if ($many_many) {
                 if ($this->append_to_top) {
                     //Upgrade all the records (including the last inserted from 0 to 1)
                     DB::query('UPDATE "' . $table . '" SET "' . $sortColumn . '" = "' . $sortColumn . '"+1' . ' WHERE "' . $parentField . '" = ' . $owner->ID . (!empty($topIncremented) ? ' AND "' . $componentField . '" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : ''));
                     $topIncremented[] = $obj->ID;
                 } else {
                     //Append the last record to the bottom
                     DB::query('UPDATE "' . $table . '" SET "' . $sortColumn . '" = ' . ($max + $i) . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID);
                 }
             } else {
                 if ($this->append_to_top) {
                     //Upgrade all the records (including the last inserted from 0 to 1)
                     DB::query('UPDATE "' . $table . '" SET "' . $sortColumn . '" = "' . $sortColumn . '"+1' . ' WHERE ' . ($list instanceof RelationList ? '"' . $list->foreignKey . '" = ' . $owner->ID : $idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : ''));
                     //LastEdited
                     DB::query('UPDATE "' . $baseDataClass . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' . ' WHERE ' . ($list instanceof RelationList ? '"' . $list->foreignKey . '" = ' . $owner->ID : $idCondition) . (!empty($topIncremented) ? ' AND "ID" NOT IN(\'' . implode('\',\'', $topIncremented) . '\')' : ''));
                     $topIncremented[] = $obj->ID;
                 } else {
                     //Append the last record to the bottom
                     DB::query('UPDATE "' . $table . '" SET "' . $sortColumn . '" = ' . ($max + $i) . ' WHERE "ID" = ' . $obj->ID);
                     //LastEdited
                     DB::query('UPDATE "' . $baseDataClass . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\'' . ' WHERE "ID" = ' . $obj->ID);
                 }
             }
             $i++;
         }
         //End transaction if supported
         if (DB::getConn()->supportsTransactions()) {
             DB::getConn()->transactionEnd();
         }
     }
 }
 /**
  * This method returns a copy of this list that does not contain any DataObjects that exists in $list
  *
  * The $list passed needs to contain the same dataclass as $this
  *
  * @param SS_List $list
  * @return DataList
  * @throws BadMethodCallException
  */
 public function subtract(SS_List $list)
 {
     if ($this->dataclass() != $list->dataclass()) {
         throw new InvalidArgumentException('The list passed must have the same dataclass as this class');
     }
     return $this->alterDataQuery(function ($query) use($list) {
         $query->subtract($list->dataQuery());
     });
 }
Example #22
0
 /**
  * This method returns a list does not contain any DataObjects that exists in $list
  * 
  * It does not return the resulting list, it only adds the constraints on the database to exclude
  * objects from $list.
  * The $list passed needs to contain the same dataclass as $this
  *
  * @param SS_List $list
  * @return DataList 
  * @throws BadMethodCallException
  */
 public function subtract(SS_List $list)
 {
     if ($this->dataclass() != $list->dataclass()) {
         throw new InvalidArgumentException('The list passed must have the same dataclass as this class');
     }
     $newlist = clone $this;
     $newlist->dataQuery->subtract($list->dataQuery());
     return $newlist;
 }
 /**
  * Gets list of safe template variables and their values which can be used
  * in both the static and editable templates.
  *
  * {@see ContentReviewAdminHelp.ss}
  *
  * @param Member     $recipient
  * @param SiteConfig $config
  * @param SS_List    $pages
  * @param string     $type
  *
  * @return array
  */
 protected function getTemplateVariables($recipient = null, $config, $pages)
 {
     if ($recipient != null) {
         return array('Subject' => $config->ReviewSubject, 'PagesCount' => $pages->count(), 'FromEmail' => $config->ReviewFrom, 'ToFirstName' => $recipient->FirstName, 'ToSurname' => $recipient->Surname, 'ToEmail' => $recipient->Email);
     } else {
         return array('Subject' => $config->ReviewSubjectReminder, 'FirstReminderPagesCount' => $pages->count(), 'SecondReminderPagesCount' => $pages->count(), 'FromEmail' => $config->ReviewFrom, 'ToEmail' => $config->ReviewReminderEmail);
     }
 }
 /**
  * If an object ID is set, add the object to the list
  *
  * @param GridField $gridField
  * @param SS_List $dataList
  * @return SS_List
  */
 public function getManipulatedData(GridField $gridField, SS_List $dataList)
 {
     $objectID = $gridField->State->GridFieldAddRelation(null);
     if (empty($objectID)) {
         return $dataList;
     }
     $object = DataObject::get_by_id($dataList->dataclass(), $objectID);
     if ($object) {
         $dataList->add($object);
     }
     $gridField->State->GridFieldAddRelation = null;
     return $dataList;
 }
	function Field($properties = array()) {
		Requirements::css(FRAMEWORK_DIR . '/css/CheckboxSetField.css');
		Requirements::javascript(FRAMEWORK_DIR . '/javascript/PermissionCheckboxSetField.js');
		
		$uninheritedCodes = array();
		$inheritedCodes = array();
		$records = ($this->records) ? $this->records : new ArrayList();
		
		// Get existing values from the form record (assuming the formfield name is a join field on the record)
		if(is_object($this->form)) {
			$record = $this->form->getRecord();
			if(
				$record 
				&& (is_a($record, 'Group') || is_a($record, 'PermissionRole')) 
				&& !$records->find('ID', $record->ID)
			) {
				$records->push($record);
			}
		}

		// Get all 'inherited' codes not directly assigned to the group (which is stored in $values)
		foreach($records as $record) {
			// Get all uninherited permissions
			$relationMethod = $this->name;
			foreach($record->$relationMethod() as $permission) {
				if(!isset($uninheritedCodes[$permission->Code])) $uninheritedCodes[$permission->Code] = array();
				$uninheritedCodes[$permission->Code][] = sprintf(
					_t('PermissionCheckboxSetField.AssignedTo', 'assigned to "%s"'),
					$record->Title
				);
			}

			// Special case for Group records (not PermissionRole):
			// Determine inherited assignments
			if(is_a($record, 'Group')) {
				// Get all permissions from roles
				if ($record->Roles()->Count()) {
					foreach($record->Roles() as $role) {
						foreach($role->Codes() as $code) {
							if (!isset($inheritedCodes[$code->Code])) $inheritedCodes[$code->Code] = array();
							$inheritedCodes[$code->Code][] = sprintf(
								_t(
									'PermissionCheckboxSetField.FromRole',
									'inherited from role "%s"',
									
									'A permission inherited from a certain permission role'
								),
								$role->Title
							);
						}
					}
				}

				// Get from parent groups
				$parentGroups = $record->getAncestors();
				if ($parentGroups) {
					foreach ($parentGroups as $parent) {
						if (!$parent->Roles()->Count()) continue;
						foreach($parent->Roles() as $role) {
							if ($role->Codes()) {
								foreach($role->Codes() as $code) {
									if (!isset($inheritedCodes[$code->Code])) $inheritedCodes[$code->Code] = array();
									$inheritedCodes[$code->Code][] = sprintf(
										_t(
											'PermissionCheckboxSetField.FromRoleOnGroup',
											'inherited from role "%s" on group "%s"',
											
											'A permission inherited from a role on a certain group'
										),
										$role->Title, 
										$parent->Title
									);
								}
							}
						}
						if ($parent->Permissions()->Count()) {
							foreach($parent->Permissions() as $permission) {
								if (!isset($inheritedCodes[$permission->Code])) $inheritedCodes[$permission->Code] = array();
								$inheritedCodes[$permission->Code][] = 
								sprintf(
									_t(
										'PermissionCheckboxSetField.FromGroup',
										'inherited from group "%s"',
										
										'A permission inherited from a certain group'
									),
									$parent->Title
								);
							}
						}
					}
				}
			}
		}
		 
		$odd = 0;
		$options = '';
		if($this->source) {
			// loop through all available categorized permissions and see if they're assigned for the given groups
			foreach($this->source as $categoryName => $permissions) {
				$options .= "<li><h5>$categoryName</h5></li>";
				foreach($permissions as $code => $permission) {
					if(in_array($code, $this->hiddenPermissions)) continue;
					if(in_array($code, Permission::$hidden_permissions)) continue;
					
					$value = $permission['name'];
			
					$odd = ($odd + 1) % 2;
					$extraClass = $odd ? 'odd' : 'even';
					$extraClass .= ' val' . str_replace(' ', '', $code);
					$itemID = $this->id() . '_' . preg_replace('/[^a-zA-Z0-9]+/', '', $code);
					$checked = $disabled = $inheritMessage = '';
					$checked = (isset($uninheritedCodes[$code]) || isset($inheritedCodes[$code])) ? ' checked="checked"' : '';
					$title = $permission['help'] ? 'title="' . htmlentities($permission['help'], ENT_COMPAT, 'UTF-8') . '" ' : '';
					
					if (isset($inheritedCodes[$code])) {
						// disable inherited codes, as any saving logic would be too complicate to express in this interface
						$disabled = ' disabled="true"';
						$inheritMessage = ' (' . join(', ', $inheritedCodes[$code]) . ')';
					} elseif($this->records && $this->records->Count() > 1 && isset($uninheritedCodes[$code])) {
						// If code assignments are collected from more than one "source group",
						// show its origin automatically
						$inheritMessage = ' (' . join(', ', $uninheritedCodes[$code]).')';
					}
					
					// If the field is readonly, always mark as "disabled"
					if($this->readonly) $disabled = ' disabled="true"';
					
					$inheritMessage = '<small>' . $inheritMessage . '</small>';
					$options .= "<li class=\"$extraClass\">" . 
						"<input id=\"$itemID\"$disabled name=\"$this->name[$code]\" type=\"checkbox\" value=\"$code\"$checked class=\"checkbox\" />" . 
						"<label {$title}for=\"$itemID\">$value$inheritMessage</label>" . 
						"</li>\n"; 
				}
			}
		}
		
		return "<ul id=\"{$this->id()}\" class=\"optionset checkboxsetfield{$this->extraClass()}\">\n$options</ul>\n"; 
	}
 public function getManipulatedData(GridField $grid, SS_List $list)
 {
     $state = $grid->getState();
     $sorted = (bool) (string) $state->GridFieldSortableHeader->SortColumn;
     // If the data has not been sorted by the user, then sort it by the
     // sort column, otherwise disable reordering.
     $state->VersionedGridFieldOrderableRows->enabled = !$sorted;
     if (!$sorted) {
         return $list->sort($this->getSortField());
     } else {
         return $list;
     }
 }
 /**
  * turns full list into paginated list
  * @param SS_List
  * @return PaginatedList
  */
 protected function paginateList(SS_List $list)
 {
     if ($list && $list->count()) {
         if ($this->IsShowFullList()) {
             $obj = PaginatedList::create($list, $this->request);
             $obj->setPageLength(EcommerceConfig::get("ProductGroup", "maximum_number_of_products_to_list") + 1);
             return $obj;
         } else {
             $obj = PaginatedList::create($list, $this->request);
             $obj->setPageLength($this->MyNumberOfProductsPerPage());
             return $obj;
         }
     }
 }
 /**
  * This is super-slow. I'm assuming if you're using facets you
  * probably also ought to be using Solr or something else. Or
  * maybe you have unlimited time and can refactor this feature
  * and submit a pull request...
  *
  * TODO: If this is going to be used for categories we're going
  * to have to really clean it up and speed it up.
  * Suggestion:
  *  - option to turn off counts
  *  - switch order of nested array so we don't go through results unless needed
  *  - if not doing counts, min/max and link facets can be handled w/ queries
  *  - separate that bit out into a new function
  * NOTE: This is partially done with the "faster_faceting" config
  * option but more could be done, particularly by covering link facets as well.
  *
  * Output - list of ArrayData in the format:
  *   Label - name of the facet
  *   Source - field name of the facet
  *   Type - one of the ShopSearch::FACET_TYPE_XXXX constants
  *   Values - SS_List of possible values for this facet
  *
  * @param SS_List $matches
  * @param array $facetSpec
  * @param bool $autoFacetAttributes [optional]
  * @return ArrayList
  */
 public function buildFacets(SS_List $matches, array $facetSpec, $autoFacetAttributes = false)
 {
     $facets = $this->expandFacetSpec($facetSpec);
     if (!$autoFacetAttributes && (empty($facets) || !$matches || !$matches->count())) {
         return new ArrayList();
     }
     $fasterMethod = (bool) $this->config()->faster_faceting;
     // fill them in
     foreach ($facets as $field => &$facet) {
         if (preg_match(self::config()->attribute_facet_regex, $field, $m)) {
             $this->buildAttributeFacet($matches, $facet, $m[1]);
             continue;
         }
         // NOTE: using this method range and checkbox facets don't get counts
         if ($fasterMethod && $facet['Type'] != ShopSearch::FACET_TYPE_LINK) {
             if ($facet['Type'] == ShopSearch::FACET_TYPE_RANGE) {
                 if (isset($facet['RangeMin'])) {
                     $facet['MinValue'] = $facet['RangeMin'];
                 }
                 if (isset($facet['RangeMax'])) {
                     $facet['MaxValue'] = $facet['RangeMax'];
                 }
             }
             continue;
         }
         foreach ($matches as $rec) {
             // If it's a range facet, set up the min/max
             if ($facet['Type'] == ShopSearch::FACET_TYPE_RANGE) {
                 if (isset($facet['RangeMin'])) {
                     $facet['MinValue'] = $facet['RangeMin'];
                 }
                 if (isset($facet['RangeMax'])) {
                     $facet['MaxValue'] = $facet['RangeMax'];
                 }
             }
             // If the field is accessible via normal methods, including
             // a user-defined getter, prefer that
             $fieldValue = $rec->relObject($field);
             if (is_null($fieldValue) && $rec->hasMethod($meth = "get{$field}")) {
                 $fieldValue = $rec->{$meth}();
             }
             // If not, look for a VFI field
             if (!$fieldValue && $rec->hasExtension('VirtualFieldIndex')) {
                 $fieldValue = $rec->getVFI($field);
             }
             // If we found something, process it
             if (!empty($fieldValue)) {
                 // normalize so that it's iterable
                 if (!is_array($fieldValue) && !$fieldValue instanceof SS_List) {
                     $fieldValue = array($fieldValue);
                 }
                 foreach ($fieldValue as $obj) {
                     if (empty($obj)) {
                         continue;
                     }
                     // figure out the right label
                     if (is_object($obj) && $obj->hasMethod('Nice')) {
                         $lbl = $obj->Nice();
                     } elseif (is_object($obj) && !empty($obj->Title)) {
                         $lbl = $obj->Title;
                     } elseif (is_numeric($obj) && !empty($facet['LabelFormat']) && $facet['LabelFormat'] === 'Currency' && $facet['Type'] !== ShopSearch::FACET_TYPE_RANGE) {
                         $tmp = Currency::create($field);
                         $tmp->setValue($obj);
                         $lbl = $tmp->Nice();
                     } else {
                         $lbl = (string) $obj;
                     }
                     // figure out the value for sorting
                     if (is_object($obj) && $obj->hasMethod('getAmount')) {
                         $val = $obj->getAmount();
                     } elseif (is_object($obj) && !empty($obj->ID)) {
                         $val = $obj->ID;
                     } else {
                         $val = (string) $obj;
                     }
                     // if it's a range facet, calculate the min and max
                     if ($facet['Type'] == ShopSearch::FACET_TYPE_RANGE) {
                         if (!isset($facet['MinValue']) || $val < $facet['MinValue']) {
                             $facet['MinValue'] = $val;
                             $facet['MinLabel'] = $lbl;
                         }
                         if (!isset($facet['RangeMin']) || $val < $facet['RangeMin']) {
                             $facet['RangeMin'] = $val;
                         }
                         if (!isset($facet['MaxValue']) || $val > $facet['MaxValue']) {
                             $facet['MaxValue'] = $val;
                             $facet['MaxLabel'] = $lbl;
                         }
                         if (!isset($facet['RangeMax']) || $val > $facet['RangeMax']) {
                             $facet['RangeMax'] = $val;
                         }
                     }
                     // Tally the value in the facets
                     if (!isset($facet['Values'][$val])) {
                         $facet['Values'][$val] = new ArrayData(array('Label' => $lbl, 'Value' => $val, 'Count' => 1));
                     } elseif ($facet['Values'][$val]) {
                         $facet['Values'][$val]->Count++;
                     }
                 }
             }
         }
     }
     // if we're auto-building the facets based on attributes,
     if ($autoFacetAttributes) {
         $facets = array_merge($this->buildAllAttributeFacets($matches), $facets);
     }
     // convert values to arraylist
     $out = new ArrayList();
     $sortValues = self::config()->sort_facet_values;
     foreach ($facets as $f) {
         if ($sortValues) {
             ksort($f['Values']);
         }
         $f['Values'] = new ArrayList($f['Values']);
         $out->push(new ArrayData($f));
     }
     return $out;
 }
 /**
  * Remove pages with empty attributes
  *
  * @param SS_List $list
  * @param string $type
  * @return SS_List
  */
 private function removeEmptyAttributes(SS_List $list, $type)
 {
     $pageAttributes = $list->map('ID', $type)->toArray();
     $emptyAttributess = array_map(function ($value) {
         return $value == '';
     }, $pageAttributes);
     if (!count($emptyAttributess)) {
         return $list;
     }
     return $list->filter(array('ID:not' => array_keys(array_filter($emptyAttributess, function ($value) {
         return $value == 1;
     }))));
 }
Example #30
0
 public function debug()
 {
     return $this->list->debug();
 }