Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Announcement_Controller
  • AnnouncementHolder_Controller
  • BookingAdminPage_Controller
  • BookingPage_Controller
  • Cart_Controller
  • CartPage_Controller
  • Catalog_Controller
  • CheckoutPage_Controller
  • ChequePayment_Handler
  • ContactsPage_Controller
  • ContentController
  • ContentNegotiator
  • Controller
  • DataObjectManager_Controller
  • DatePickerField_Controller
  • Director
  • DocPage_Controller
  • DocumentsPage_Controller
  • Event_Controller
  • EventHolder_Controller
  • FileDataObjectManager_Controller
  • FindCyrillic_Controller
  • HomePage_Controller
  • LastDoc_Controller
  • LiveCalendarWidget_Controller
  • MapObject_Controller
  • MapObjectGroup_Controller
  • MapPage_Controller
  • MediawebPage_Controller
  • ModelAsController
  • MultiUploadControls
  • NewsArchive
  • Orders1CExchange_Controller
  • Page_Controller
  • Payment_Handler
  • PhotoAlbumManager_Controller
  • Product_Controller
  • ProductSearchPage_Controller
  • ProfilePage_Controller
  • PublHolder_Controller
  • Publication_Controller
  • RatingExtension_Controller
  • RegistrationPage_Controller
  • RemoveOrphanedPagesTask
  • RequestHandler
  • Room_Controller
  • RoomCatalog_Controller
  • RootURLController
  • SapphireInfo
  • Search_Controller
  • Session
  • SimpleOrderPage_Controller
  • SiteMap_Controller
  • SpecialCatalog_Controller
  • SS_HTTPRequest
  • SS_HTTPResponse
  • StartCatalog_Controller
  • SubsitesSelectorPage_Controller
  • VideoBankPage_Controller

Interfaces

  • NestedController

Exceptions

  • SS_HTTPResponse_Exception
   1 <?php
   2 
   3 class DataObjectManager extends ComplexTableField {
   4 
   5     protected static $allow_assets_override = true;
   6     protected static $allow_css_override = false;
   7     protected static $popup_width = 500;
   8     protected static $confirm_delete = true;
   9 
  10     protected $template = "DataObjectManager";
  11     protected $start = "0";
  12     protected $per_page = "20";
  13     protected $showAll = "0";
  14     protected $search = "";
  15     protected $filter = "";
  16     protected $sort_dir = "DESC";
  17     protected $sort = "Created";
  18     protected $filter_map = array();
  19     protected $filtered_field;
  20     protected $filter_label = "Filter results";
  21     protected $filter_empty_string = "";
  22     protected $column_widths = array();
  23     protected $per_page_map = array('10','20','30','40','50');
  24     protected $use_view_all = true;
  25     protected $popupWidth;
  26     protected $confirmDelete;
  27     public $itemClass = "DataObjectManager_Item";
  28     public $addTitle;
  29     public $singleTitle;
  30     public $hasNested = false;
  31     public $isNested = false;
  32 
  33 
  34     public $actions = array(
  35             'edit' => array(
  36                             'label' => 'Edit',
  37                             'icon' => null,
  38                             'class' => 'popuplink editlink',
  39             ),
  40             'delete' => array(
  41                             'label' => 'Delete',
  42                             'icon' => null,
  43                             'class' => 'deletelink',
  44             )
  45     );
  46 
  47     static $url_handlers = array(
  48             'duplicate/$ID' => 'handleDuplicate'
  49     );
  50 
  51 
  52     public $popupClass = "DataObjectManager_Popup";
  53     public $templatePopup = "DataObjectManager_popup";
  54 
  55     public static function allow_assets_override($bool) {
  56         if($bool) {
  57             DataObject::add_extension("Folder","AssetManagerFolder");
  58             SortableDataObject::add_sortable_class("File");
  59         }
  60         else
  61             DataObject::remove_extension("Folder","AssetManagerFolder");
  62     }
  63 
  64     public static function allow_css_override($bool) {
  65         self::$allow_css_override = $bool;
  66     }
  67 
  68     public static function set_popup_width($width) {
  69         self::$popup_width = $width;
  70     }
  71 
  72     public static function set_confirm_delete($bool) {
  73         self::$confirm_delete = $bool;
  74     }
  75 
  76     function __construct($controller, $name = null, $sourceClass = null, $fieldList = null, $detailFormFields = null, $sourceFilter = "", $sourceSort = "Created DESC", $sourceJoin = "") {
  77         if(!class_exists("ComplexTableField_ItemRequest"))
  78             die("<strong>"._t('DataObjectManager.ERROR','Error')."</strong>: "._t('DataObjectManager.SILVERSTRIPEVERSION','DataObjectManager requires Silverstripe version 2.3 or higher.'));
  79 
  80         // If no name is given, search the has_many for the first relation.
  81         if($name === null && $sourceClass === null) {
  82             if($has_manys = $controller->stat('has_many')) {
  83                 foreach($has_manys as $relation => $value) {
  84                     $name = $relation;
  85                     $sourceClass = $value;
  86                     break;
  87                 }
  88             }
  89         }
  90         $SNG = singleton($sourceClass);
  91         if($fieldList === null) {
  92             if($fields = $SNG->summaryFields()) {
  93                 $fieldList = $fields;
  94             }
  95             else if($db = $SNG->db()) {
  96                 $fieldList = array();
  97                 foreach($db as $field => $type) {
  98                     if($field != "SortOrder")
  99                         $fieldList[$field] = DOMUtil::readable_class($field);
 100                 }
 101             }
 102         }
 103         parent::__construct($controller, $name, $sourceClass, $fieldList, $detailFormFields, $sourceFilter, $sourceSort, $sourceJoin);
 104         Requirements::css('dataobject_manager/css/dataobject_manager.css');
 105         Requirements::css('dataobject_manager/css/facebox.css');
 106         if(self::$allow_css_override)
 107             Requirements::css('dataobject_manager/css/dataobjectmanager_override.css');
 108         Requirements::javascript(THIRDPARTY_DIR.'/jquery-livequery/jquery.livequery.js');
 109         Requirements::javascript('dataobject_manager/javascript/facebox.js');
 110         Requirements::javascript('dataobject_manager/javascript/dom_jquery_ui.js');
 111         Requirements::javascript('dataobject_manager/javascript/tooltip.js');
 112         Requirements::javascript('dataobject_manager/javascript/dataobject_manager.js');
 113 
 114         $this->filter_empty_string = '-- '._t('DataObjectManager.NOFILTER','No filter').' --';
 115 
 116         if($this->sourceSort) {
 117             $parts = explode(" " , $this->sourceSort);
 118             if(is_array($parts) && sizeof($parts) == 2) {
 119                 list($field,$dir) = $parts;
 120                 $this->sort = trim($field);
 121                 $this->sort_dir = trim($dir);
 122             }
 123             else {
 124                 $this->sort = $this->sourceSort;
 125                 $this->sort_dir = "ASC";
 126             }
 127         }
 128 
 129         if(isset($_REQUEST['ctf'][$this->Name()])) {
 130             $this->start = isset($_REQUEST['ctf'][$this->Name()]['start']) ? $_REQUEST['ctf'][$this->Name()]['start'] : 0;
 131             $this->per_page = $_REQUEST['ctf'][$this->Name()]['per_page'];
 132             $this->showAll = $_REQUEST['ctf'][$this->Name()]['showall'];
 133             $this->search = $_REQUEST['ctf'][$this->Name()]['search'];
 134             $this->filter = $_REQUEST['ctf'][$this->Name()]['filter'];
 135             $this->sort = $_REQUEST['ctf'][$this->Name()]['sort'];
 136             $this->sort_dir = $_REQUEST['ctf'][$this->Name()]['sort_dir'];
 137         }
 138 
 139 
 140         $this->setPageSize($this->per_page);
 141         $this->loadSort();
 142         $this->loadSourceFilter();
 143 
 144         $fields = $this->getRawDetailFields(singleton($this->sourceClass()));
 145         foreach($fields as $field) {
 146             if($field instanceof DataObjectManager && !($field->controller instanceof SiteTree)) {
 147                 $this->hasNested = true;
 148                 $this->setPopupWidth(850);
 149             }
 150         }
 151 
 152     }
 153 
 154     public function setSourceFilter($filter) {
 155         $this->sourceFilter = $filter;
 156     }
 157 
 158     public function setUseViewAll($bool) {
 159         $this->use_view_all = $bool;
 160     }
 161 
 162     public function setPerPageMap($values) {
 163         $this->per_page_map = $values;
 164     }
 165 
 166     public function setPluralTitle($title) {
 167         $this->pluralTitle = $title;
 168     }
 169 
 170     public function setWideMode($bool) {
 171         $this->hasNested = $bool;
 172     }
 173 
 174     public function PluralTitle() {
 175         return $this->pluralTitle ? $this->pluralTitle : $this->AddTitle()."";
 176     }
 177 
 178 
 179     protected function loadSort() {
 180         if($this->ShowAll())
 181             $this->setPageSize(999);
 182 
 183         if($this->Sortable() && (!isset($_REQUEST['ctf'][$this->Name()]['sort']) || $_REQUEST['ctf'][$this->Name()]['sort'] == "SortOrder")) {
 184             $this->sort = "SortOrder";
 185             $this->sourceSort = "SortOrder ASC";
 186             $this->sort_dir = "ASC";
 187         }
 188         elseif(isset($_REQUEST['ctf'][$this->Name()]['sort'])) {
 189             $this->sourceSort = $_REQUEST['ctf'][$this->Name()]['sort'] . " " . $this->sort_dir;
 190         }
 191 
 192     }
 193 
 194     protected function loadSourceFilter() {
 195         $filter_string = "";
 196         if(!empty($this->filter)) {
 197             $break = strpos($this->filter, "_");
 198             $field = substr($this->filter, 0, $break);
 199             $value = substr($this->filter, $break+1, strlen($this->filter) - strlen($field));
 200             $filter_string = $field . "='$value'";
 201         }
 202 
 203         $search_string = "";
 204         if(!empty($this->search)) {
 205             $search = array();
 206             $SNG = singleton($this->sourceClass);
 207             foreach(parent::Headings() as $field) {
 208                 if($SNG->hasDatabaseField($field->Name))
 209                     $search[] = "UPPER($field->Name) LIKE '%".strtoupper($this->search)."%'";
 210             }
 211             $search_string = "(".implode(" OR ", $search).")";
 212         }
 213         $and = (!empty($this->filter) && !empty($this->search)) ? " AND " : "";
 214         $source_filter = $filter_string.$and.$search_string;
 215         if(!$this->sourceFilter) $this->sourceFilter = $source_filter;
 216         else if($this->sourceFilter && !empty($source_filter)) $this->sourceFilter .= " AND " . $source_filter;
 217     }
 218 
 219     public function handleItem($request) {
 220         return new DataObjectManager_ItemRequest($this, $request->param('ID'));
 221     }
 222 
 223     public function getQueryString($params = array()) {
 224         $start    = isset($params['start'])? $params['start']       :   $this->start;
 225         $per_page = isset($params['per_page'])? $params['per_page'] :   $this->per_page;
 226         $show_all = isset($params['show_all'])? $params['show_all'] :   $this->showAll;
 227         $sort     = isset($params['sort'])? $params['sort']             :   $this->sort;
 228         $sort_dir = isset($params['sort_dir'])? $params['sort_dir'] :   $this->sort_dir;
 229         $filter   = isset($params['filter'])? $params['filter']       :     $this->filter;
 230         $search   = isset($params['search'])? $params['search']       :     $this->search;
 231         
 232         $url = "ctf[{$this->Name()}][start]={$start}&ctf[{$this->Name()}][per_page]={$per_page}&ctf[{$this->Name()}][showall]={$show_all}&ctf[{$this->Name()}][sort]={$sort}&ctf[{$this->Name()}][sort_dir]={$sort_dir}&ctf[{$this->Name()}][search]={$search}&ctf[{$this->Name()}][filter]={$filter}";
 233         if (Translatable::get_allowed_locales()) {
 234             $url .= "&locale=" . Translatable::get_current_locale();
 235         }       
 236         return $url;
 237     }
 238 
 239     public function getSetting($setting) {
 240         if($this->$setting) {
 241             return $this->$setting;
 242         }
 243         return Object::get_static($this->class,DOMUtil::to_underscore($setting));
 244     }
 245 
 246     function FieldHolder() {
 247         if(!$this->controller->ID && $this->isNested)
 248             return $this->renderWith('DataObjectManager_holder');
 249         return parent::FieldHolder();
 250     }
 251 
 252 
 253     public function Headings() {
 254         $headings = array();
 255         foreach($this->fieldList as $fieldName => $fieldTitle) {
 256             if(isset($_REQUEST['ctf'][$this->Name()]['sort_dir']))
 257                 $dir = $_REQUEST['ctf'][$this->Name()]['sort_dir'] == "ASC" ? "DESC" : "ASC";
 258             else
 259                 $dir = "ASC";
 260             $headings[] = new ArrayData(array(
 261                             "Name" => $fieldName,
 262                             "Title" => ($this->sourceClass) ? singleton($this->sourceClass)->fieldLabel($fieldTitle) : $fieldTitle,
 263                             "IsSortable" => singleton($this->sourceClass)->hasDatabaseField($fieldName),
 264                             "SortLink" => $this->RelativeLink(array(
 265                             'sort_dir' => $dir,
 266                             'sort' => $fieldName
 267                             )),
 268                             "SortDirection" => $dir,
 269                             "IsSorted" => (isset($_REQUEST['ctf'][$this->Name()]['sort'])) && ($_REQUEST['ctf'][$this->Name()]['sort'] == $fieldName),
 270                             "ColumnWidthCSS" => !empty($this->column_widths) ? sprintf("style='width:%f%%;'",($this->column_widths[$fieldName] - 0.1)) : ""
 271             ));
 272         }
 273         return new DataObjectSet($headings);
 274     }
 275 
 276     function saveComplexTableField($data, $form, $params) {
 277         $className = $this->sourceClass();
 278         $childData = new $className();
 279         $form->saveInto($childData);
 280         $childData->write();
 281         if($childData->many_many()) {
 282             $form->saveInto($childData);
 283             $childData->write();
 284         }
 285         $form->sessionMessage(sprintf(_t('DataObjectManager.ADDEDNEW','Added new %s successfully'),$this->SingleTitle()), 'good');
 286 
 287         if($form->getFileFields() || $form->getNestedDOMs()) {
 288             $form->clearMessage();
 289             Director::redirect(Controller::join_links($this->BaseLink(),'/item/'.$childData->ID.'/edit'));
 290         }
 291         else Director::redirectBack();
 292 
 293     }
 294 
 295     function sourceID() {
 296         if($this->isNested)
 297             return $this->controller->ID;
 298         $idField = $this->form->dataFieldByName('ID');
 299         return ($idField && is_numeric($idField->Value())) ? $idField->Value() : (isset($_REQUEST['ctf']['ID']) ? $_REQUEST['ctf']['ID'] : null);
 300     }
 301 
 302 
 303     protected function getRawDetailFields($childData) {
 304         if(is_a($this->detailFormFields,"Fieldset"))
 305             $fields = $this->detailFormFields;
 306         else {
 307             if(!is_string($this->detailFormFields)) $this->detailFormFields = "getCMSFields";
 308             $functioncall = $this->detailFormFields;
 309             if(!$childData->hasMethod($functioncall)) $functioncall = "getCMSFields";
 310 
 311             $fields = $childData->$functioncall();
 312         }
 313         return $fields;
 314     }
 315 
 316     public function getCustomFieldsFor($childData) {
 317         $fields = $this->getRawDetailFields($childData);
 318         foreach($fields as $field) {
 319             if($field->class == "CalendarDateField")
 320                 $fields->replaceField($field->Name(), new DatePickerField($field->Name(), $field->Title(), $field->attrValue()));
 321         }
 322         return $fields;
 323     }
 324 
 325     function AddForm($childID = null) {
 326         $form = parent::AddForm($childID);
 327         $actions = new FieldSet();
 328         $titles = array();
 329         if($files = $form->getFileFields()) {
 330             foreach($files as $field)   $titles[] = DOMUtil::readable_class($field->Title());
 331         }
 332         if($doms = $form->getNestedDOMs())
 333             foreach($doms as $field) $titles[] = $field->PluralTitle();
 334         if(empty($titles))
 335             $text = _t('DataObjectManager.SAVE','Save');
 336         elseif(sizeof($titles) > 3) {
 337             $first_three = array_slice($titles,0,3);
 338             $remaining = sizeof(array_slice($titles, 4));
 339             $text = sprintf(_t('DataObjectManager.SAVEANDADD','Save and add %s'), implode(', ',$first_three));
 340             $text .= ", " . sprintf(_t('DataObjectManager.ANDOTHERCOMPONENTS','and %d other components'),$remaining);
 341         }
 342         else
 343             $text = sprintf(_t('DataObjectManager.SAVEANDADD','Save and add %s'), DOMUtil::readable_list($titles));
 344 
 345         $actions->push(
 346                 $saveAction = new FormAction("saveComplexTableField", $text)
 347         );
 348         $saveAction->addExtraClass('save');
 349         $form->setActions($actions);
 350         return $form;
 351     }
 352 
 353     public function Link($action = null) {
 354         return Controller::join_links(parent::Link($action),'?'.$this->getQueryString());
 355     }
 356 
 357     public function BaseLink() {
 358         return parent::Link();
 359     }
 360 
 361     public function CurrentLink() {
 362         return $this->Link();
 363     }
 364 
 365     public function RelativeLink($params = array()) {
 366         return Controller::join_links(parent::Link(),'?'.$this->getQueryString($params));
 367     }
 368     public function FirstLink() {
 369         return parent::FirstLink() ? $this->RelativeLink(array('start' => '0')) : false;
 370     }
 371 
 372     public function PrevLink() {
 373         $start = ($this->start - $this->pageSize < 0)  ? 0 : $this->start - $this->pageSize;
 374         return parent::PrevLink() ? $this->RelativeLink(array('start' => $start)) : false;
 375     }
 376 
 377     public function NextLink() {
 378         $currentStart = isset($_REQUEST['ctf'][$this->Name()]['start']) ? $_REQUEST['ctf'][$this->Name()]['start'] : 0;
 379         $start = ($currentStart + $this->pageSize < $this->TotalCount()) ? $currentStart + $this->pageSize : $this->TotalCount() % $this->pageSize > 0;
 380         return parent::NextLink() ? $this->RelativeLink(array('start' => $start)) : false;
 381     }
 382 
 383     public function LastLink() {
 384         $pageSize = ($this->TotalCount() % $this->pageSize > 0) ? $this->TotalCount() % $this->pageSize : $this->pageSize;
 385         $start = $this->TotalCount() - $pageSize;
 386         return parent::LastLink() ? $this->RelativeLink(array('start' => $start)) : false;
 387     }
 388 
 389     public function ShowAllLink() {
 390         return $this->RelativeLink(array('show_all' => '1'));
 391     }
 392 
 393     public function PaginatedLink() {
 394         return $this->RelativeLink(array('show_all' => '0'));
 395     }
 396 
 397     public function AddLink() {
 398         return Controller::join_links($this->BaseLink(), '/add');
 399     }
 400 
 401     public function ShowAll() {
 402         return $this->showAll == "1";
 403     }
 404 
 405     public function Paginated() {
 406         return $this->showAll == "0";
 407     }
 408 
 409     public function Sortable() {
 410         return SortableDataObject::is_sortable_class($this->sourceClass());
 411     }
 412 
 413     public function setFilter($field, $label, $map, $default = null) {
 414         if(is_array($map)) {
 415             $this->filter_map = $map;
 416             $this->filtered_field = $field;
 417             $this->filter_label = $label;
 418         }
 419         if($default) {
 420             $this->filter = $this->filtered_field.'_'.$default;
 421             $this->loadSourceFilter();
 422         }
 423     }
 424 
 425     public function HasFilter() {
 426         return !empty($this->filter_map);
 427     }
 428 
 429     public function FilterDropdown() {
 430         $map = $this->filter_empty_string ? array($this->RelativeLink(array('filter' => '')) => $this->filter_empty_string) : array();
 431         foreach($this->filter_map as $k => $v) {
 432             $map[$this->RelativeLink(array('filter' => $this->filtered_field.'_'.$k))] = $v;
 433         }
 434         $value = !empty($this->filter) ? $this->RelativeLink(array('filter' => $this->filter)) : null;
 435         $dropdown = new DropdownField('Filter',$this->filter_label . " (<a href='#' class='refresh'>"._t('DataObjectManager.REFRESH','refresh')."</a>)", $map, $value);
 436         return $dropdown->FieldHolder();
 437     }
 438 
 439     public function PerPageDropdown() {
 440         $map = array();
 441         foreach($this->per_page_map as $num) $map[$this->RelativeLink(array('per_page' => $num))] = $num;
 442         if($this->use_view_all)
 443             $map[$this->RelativeLink(array('per_page' => '9999'))] = _t('DataObjectManager.ALL','All');
 444         $value = !empty($this->per_page) ? $this->RelativeLink(array('per_page' => $this->per_page)) : null;
 445         return new FieldGroup(
 446                 new LabelField('show', _t('DataObjectManager.PERPAGESHOW','Show').' '),
 447                 new DropdownField('PerPage',_t('DataObjectManager.DDPERPAGESHOW'),$map, $value),
 448                 new LabelField('results', ' '._t('DataObjectManager.PERPAGERESULTS','results per page'))
 449 
 450         );
 451     }
 452     public function SearchValue() {
 453         return !empty($this->search) ? $this->search : false;
 454     }
 455 
 456     public function AddTitle() {
 457         return $this->addTitle ? $this->addTitle : DOMUtil::readable_class($this->Title());
 458     }
 459 
 460     public function SingleTitle() {
 461         return $this->singleTitle ? $this->singleTitle : DOMUtil::readable_class($this->AddTitle());
 462     }
 463 
 464     public function setAddTitle($title) {
 465         $this->addTitle = $title;
 466     }
 467 
 468     public function setSingleTitle($title) {
 469         $this->singleTitle = $title;
 470     }
 471 
 472     public function getColumnWidths() {
 473         return $this->column_widths;
 474     }
 475 
 476     public function setColumnWidths($widths) {
 477         if(is_array($widths)) {
 478             $total = 0;
 479             foreach($widths as $name => $value) $total += $value;
 480             if($total != 100)
 481                 die('<strong>DataObjectManager::setColumnWidths()</strong>:' . sprintf(_t('DataObjectManager.TOTALNOT100','Column widths must total 100 and not %s'), $total));
 482             else
 483                 $this->column_widths = $widths;
 484         }
 485     }
 486 
 487     public function setFilterEmptyString($str) {
 488         $this->filter_empty_string = $str;
 489     }
 490 
 491     public function addPermission($perm) {
 492         if(!in_array($perm,$this->permissions))
 493             $this->permissions[] = $perm;
 494     }
 495 
 496     public function removePermission($perm) {
 497         $key = array_search($perm,$this->permissions);
 498         if($key !== false)
 499             unset($this->permissions[$key]);
 500     }
 501 
 502     public function NestedType() {
 503         if($this->hasNested)
 504             return "hasNested";
 505         else if($this->isNested)
 506             return "isNested";
 507         else
 508             return "";
 509     }
 510 
 511     public function handleDuplicate($request) {
 512         return new DataObjectManager_ItemRequest($this,$request->param('ID'));
 513     }
 514 
 515     public function setPopupWidth($val) {
 516         $this->popupWidth = $val;
 517     }
 518 
 519     public function setConfirmDelete($bool) {
 520         $this->confirmDelete = $bool;
 521     }
 522 
 523     public function PopupWidth() {
 524         return $this->getSetting('popupWidth');
 525     }
 526 
 527     public function ConfirmDelete() {
 528         return $this->getSetting('confirmDelete');
 529     }
 530 
 531 
 532 
 533 }
 534 
 535 class DataObjectManager_Item extends ComplexTableField_Item {
 536     function __construct(DataObject $item, DataObjectManager $parent) {
 537         parent::__construct($item, $parent);
 538     }
 539 
 540     function Link($action = NULL) {
 541         return Controller::join_links($this->parent->BaseLink(), '/item/' . $this->item->ID);
 542     }
 543 
 544     function Fields($xmlSafe = true) {
 545         $fields = parent::Fields($xmlSafe);
 546         $widths = $this->parent->getColumnWidths();
 547         if(!empty($widths)) {
 548             foreach($fields as $field) {
 549                 $field->ColumnWidthCSS = sprintf("style='width:%f%%;'",($widths[$field->Name] - 0.1));
 550             }
 551         }
 552         return $fields;
 553     }
 554 
 555     public function CanViewOrEdit() {
 556         return $this->parent->Can('view') || $this->parent->Can('edit');
 557     }
 558     
 559     function CanDelete() {
 560         return $this->parent->Can('delete');
 561     }
 562 
 563     public function ViewOrEdit() {
 564         if($this->CanViewOrEdit())
 565             return $this->parent->Can('edit') ? "edit" : "view";
 566         return false;
 567     }
 568 
 569     public function ViewOrEdit_i18n() {
 570         if($res = $this->ViewOrEdit()) {
 571             return ($res == "edit") ? _t('DataObjectManager.EDIT','Edit') : _t('DataObjectManager.VIEW','View');
 572         }
 573         return null;
 574     }
 575 
 576     public function EditLink() {
 577         //return $this->Link()."/edit?".$this->parent->getQueryString();
 578         return Controller::join_links($this->Link(), "edit?").$this->parent->getQueryString();
 579     }
 580 
 581     public function DuplicateLink() {
 582         return Controller::join_links($this->Link(), "/duplicate");
 583     }
 584 
 585     public function CustomActions() {
 586         if($this->item->hasMethod('customDOMActions'))
 587             return $this->item->customDOMActions();
 588         return false;
 589     }
 590 
 591     public function PopupWidth() {
 592         return $this->parent->PopupWidth();
 593     }
 594 
 595     public function Actions() {
 596         $actions = new DataObjectSet();
 597         // Inxo FIX for PHP 5.2.0
 598         // TODO: After upgrade PHP 5.2.8+ need update
 599         // Не нужно, если с 2.4 subsites заработает
 600         // В 2.4 не заработало, а из-за смены ModelAdmin еще и усугубило
 601         $permList = (array) $this->parent->permissions;
 602         foreach($permList as $perm) {
 603             $action = false;
 604             switch($perm) {
 605                 case "edit":
 606                 case "view":
 607                     $actions->push(new DataObjectManagerAction(
 608                             $this->ViewOrEdit_i18n(),
 609                             $this->EditLink(),
 610                             "popup",
 611                             "dataobject_manager/images/page_white_{$this->ViewOrEdit()}.png",
 612                             "editlink"  ,
 613                             $this->parent->PopupWidth()
 614                     ));
 615                     break;
 616 
 617                 case "delete":
 618                     $actions->push(new DataObjectManagerAction(
 619                             _t('DataObjectManager.DELETE','Delete'),
 620                             $this->DeleteLink(),
 621                             "delete",
 622                             "dataobject_manager/images/trash.gif",
 623                             null,
 624                             $this->parent->getSetting('confirmDelete') ? "confirm" : null
 625                     ));
 626                     break;
 627 
 628                 case "duplicate":
 629                     $actions->push(new DataObjectManagerAction(
 630                             _t('DataObjectManager.DUPLICATE','Duplicate'),
 631                             $this->DuplicateLink(),
 632                             "popup",
 633                             "dataobject_manager/images/page_copy.png",
 634                             null,
 635                             400
 636                     ));
 637                     break;
 638             }
 639         }
 640         if($custom = $this->CustomActions()) {
 641             if($custom instanceof DataObjectSet)
 642                 $actions->merge($custom);
 643             else
 644                 $actions->push($custom);
 645         }
 646         return $actions;
 647     }
 648 }
 649 
 650 class DataObjectManager_Controller extends Controller {
 651     public function dosort() {
 652         if(!empty($_POST) && is_array($_POST) && isset($this->urlParams['ID'])) {
 653             $className = $this->urlParams['ID'];
 654             if(stristr($className,"-") !== false) {
 655                 list($ownerClass, $className) = explode("-",$className);
 656             }
 657             $many_many = ((is_numeric($this->urlParams['OtherID'])) && SortableDataObject::is_sortable_many_many($className));
 658             foreach($_POST as $group => $map) {
 659                 if(substr($group, 0, 7) == "record-") {
 660                     if($many_many) {
 661                         $controllerID = $this->urlParams['OtherID'];
 662                         $candidates = singleton($ownerClass)->many_many();
 663                         if(is_array($candidates)) {
 664                             foreach($candidates as $name => $class)
 665                                 if($class == $className) {
 666                                     $relationName = $name;
 667                                     break;
 668                                 }
 669                         }
 670                         if(!isset($relationName)) return false;
 671                         list($parentClass, $componentClass, $parentField, $componentField, $table) = singleton($ownerClass)->many_many($relationName);
 672                         foreach($map as $sort => $id)
 673                             DB::query("UPDATE `$table` SET SortOrder = $sort WHERE {$className}ID = $id AND {$ownerClass}ID = $controllerID");
 674                     }
 675                     else {
 676                         foreach($map as $sort => $id) {
 677                             $obj = DataObject::get_by_id($className, $id);
 678                             $obj->SortOrder = $sort;
 679                             $obj->write();
 680                         }
 681                     }
 682                     break;
 683                 }
 684             }
 685         }
 686     }
 687     public function i18n_js() {
 688         return Convert::array2json(array(
 689                 'delete_confirm' => _t('DataObjectManager.CONFIRMDELETE','Delete?')
 690         ));
 691     }
 692 }
 693 
 694 
 695 
 696 class DataObjectManager_Popup extends Form {
 697     protected $sourceClass;
 698     protected $dataObject;
 699     public $NestedController = false;
 700 
 701     function __construct($controller, $name, $fields, $validator, $readonly, $dataObject) {
 702         $this->dataObject = $dataObject;
 703         Requirements::clear();
 704         Requirements::clear_combined_files();
 705         Requirements::unblock_all();
 706         Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/prototype/prototype.js');
 707         Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/behaviour/behaviour.js');
 708         Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/jquery/jquery.js');
 709         Requirements::javascript(SAPPHIRE_DIR . '/javascript/jquery_improvements.js');
 710         Requirements::javascript(THIRDPARTY_DIR.'/jquery-livequery/jquery.livequery.js');
 711         
 712         //Requirements::block(THIRDPARTY_DIR.'/behaviour.js');
 713         //Requirements::block(SAPPHIRE_DIR.'/javascript/Validator.js');
 714         //Requirements::block(THIRDPARTY_DIR.'/prototype.js');
 715         //Requirements::clear(THIRDPARTY_DIR.'/behavior.js');
 716         //Requirements::block(THIRDPARTY_DIR.'/behavior.js');
 717         Requirements::block(SAPPHIRE_DIR.'/javascript/ComplexTableField.js');
 718         Requirements::block(SAPPHIRE_DIR.'/javascript/TableListField.js');
 719         Requirements::block(THIRDPARTY_DIR.'/greybox/greybox.js');
 720         Requirements::block(THIRDPARTY_DIR.'/greybox/AmiJS.js');
 721         Requirements::block(THIRDPARTY_DIR.'/greybox/greybox.css');
 722         Requirements::block(SAPPHIRE_DIR.'/css/TableListField.css');
 723         Requirements::block(SAPPHIRE_DIR.'/css/ComplexTableField.css');
 724         Requirements::block(ASSETS_DIR.'/leftandmain.js');
 725         Requirements::block(ASSETS_DIR.'/base.js');
 726         Requirements::block(SAPPHIRE_DIR.'/javascript/lang/en_US.js');
 727         Requirements::css(SAPPHIRE_DIR . '/css/Form.css');
 728         Requirements::css(CMS_DIR . '/css/typography.css');
 729         Requirements::css(CMS_DIR . '/css/cms_right.css');
 730         Requirements::css('dataobject_manager/css/dataobject_manager.css');
 731         
 732         // Append requirements from instance callbacks
 733         $parent = $controller;
 734         if($parent instanceof DataObjectManager) {
 735             $callback = $parent->requirementsForPopupCallback;
 736         } else {
 737             $callback = $parent->getParentController()->requirementsForPopupCallback;
 738         }
 739         if($callback) call_user_func($callback, $this);
 740         // DEPREDICATED 2.4
 741         if($this->dataObject->hasMethod('getRequirementsForPopup')) {
 742             $this->dataObject->getRequirementsForPopup();
 743         }
 744         Requirements::javascript('dataobject_manager/javascript/dataobjectmanager_popup.js');
 745 
 746 
 747         $actions = new FieldSet();
 748         if(!$readonly) {
 749             $actions->push(
 750                     $saveAction = new FormAction("saveComplexTableField", _t('DataObjectManager.SAVE','Save'))
 751 
 752             );
 753             $saveAction->addExtraClass('save');
 754         }
 755 
 756         parent::__construct($controller, $name, $fields, $actions, $validator);
 757         $this->unsetValidator();
 758 
 759         if($this->getNestedDOMs()) {
 760             Requirements::javascript(THIRDPARTY_DIR.'/jquery-livequery/jquery.livequery.js');
 761             Requirements::javascript('dataobject_manager/javascript/dom_jquery_ui.js');
 762             Requirements::javascript('dataobject_manager/javascript/tooltip.js');
 763             Requirements::javascript('dataobject_manager/javascript/dataobject_manager.js');
 764         }
 765         $this->NestedController = $this->controller->isNested;
 766     }
 767 
 768     function FieldHolder() {
 769         return $this->renderWith('ComplexTableField_Form');
 770     }
 771 
 772     public function getFileFields() {
 773         $file_fields = array();
 774         foreach($this->Fields() as $field) {
 775             if($field instanceof FileIFrameField || $field instanceof ImageField)
 776                 $file_fields[] = $field;
 777         }
 778         return !empty($file_fields)? $file_fields : false;
 779     }
 780 
 781     public function getNestedDOMs() {
 782         $dom_fields = array();
 783         foreach($this->Fields()->dataFields() as $field) {
 784             if($field instanceof DataObjectManager) {
 785                 $field->isNested = true;
 786                 $dom_fields[] = $field;
 787             }
 788             elseif($field instanceof CompositeField) {
 789                 if($children = $field->children) {
 790                     foreach($children as $child) {
 791                         if($child instanceof DataObjectManager) {
 792                             $child->isNested = true;
 793                             $dom_fields[] = $child;
 794                         }
 795                     }
 796                 }
 797             }
 798         }
 799         return !empty($dom_fields)? $dom_fields : false;
 800     }
 801     function getParentController() {
 802         return $this->controller;
 803     }
 804 
 805 }
 806 
 807 
 808 
 809 class DataObjectManager_ItemRequest extends ComplexTableField_ItemRequest {
 810     public $isNested = false;
 811     protected $itemList;
 812     protected $currentIndex;
 813 
 814     function __construct($ctf, $itemID) {
 815         parent::__construct($ctf, $itemID);
 816         $this->isNested = $this->ctf->isNested;
 817         if($this->ctf->Items()) {
 818             $this->itemList = $this->ctf->Items()->column();
 819             $this->currentIndex = array_search($this->itemID,$this->itemList);
 820         }
 821     }
 822 
 823     function Link($action = NULL) {
 824         return Controller::join_links($this->ctf->BaseLink() , '/item/' . $this->itemID);
 825     }
 826 
 827     function saveComplexTableField($data, $form, $request) {
 828         $dataObject = $this->dataObj();
 829         $form->saveInto($dataObject);
 830         $dataObject->write();
 831         // Save the many many relationship if it's available
 832         if(isset($data['ctf']['manyManyRelation'])) {
 833             $parentRecord = DataObject::get_by_id($data['ctf']['parentClass'], (int) $data['ctf']['sourceID']);
 834             $relationName = $data['ctf']['manyManyRelation'];
 835             $componentSet = $parentRecord->getManyManyComponents($relationName);
 836             $componentSet->add($dataObject);
 837         }
 838 
 839         $form->sessionMessage(sprintf(_t('DataObjectManager.SAVED','Saved %s successfully'),$this->ctf->SingleTitle()), 'good');
 840 
 841         Director::redirectBack();
 842     }
 843 
 844     function DetailForm($childID = null) {
 845         $form = parent::DetailForm($childID);
 846         $form->Fields()->insertFirst(new LiteralField('open','<div id="field-holder"><div id="fade"></div>'));
 847         $o = $form->Fields()->Last();
 848         $form->Fields()->insertAfter(new LiteralField('close','</div>'),$o->Name());
 849         if(!$this->ctf->Can('edit')) {
 850             $form->makeReadonly();
 851             $form->setActions(null);
 852         }
 853         return $form;
 854     }
 855 
 856     function edit() {
 857         if(!$this->ctf->Can('view') && !$this->ctf->Can('edit'))
 858             return false;
 859 
 860         $this->methodName = "edit";
 861 
 862         echo $this->renderWith($this->ctf->templatePopup);
 863     }
 864 
 865     public function duplicate() {
 866         if(!$this->ctf->Can('duplicate'))
 867             return false;
 868         $this->methodName = "duplicate";
 869 
 870         echo $this->renderWith(array('DataObjectManager_duplicate'));
 871     }
 872 
 873     public function DuplicateForm() {
 874         return new Form(
 875                 $this,
 876                 "DuplicateForm",
 877                 new FieldSet(
 878                 new FieldGroup(
 879                 new LabelField('copy',_t('DataObjectManager.CREATE','Create ')),
 880                 new NumericField('Count','','1'),
 881                 new LabelField('times',sprintf(_t('DataObjectManager.COPIESOFOBJECT',' copies of this %s'),$this->ctf->SingleTitle()))
 882                 ),
 883                 new CheckboxField('Relations',_t('DataObjectManager.INCLUDERELATIONS','Include related objects'))
 884                 ),
 885                 new FieldSet(
 886                 new FormAction('doDuplicate',_t('DataObjectManager.DUPLICATE','Duplicate'))
 887                 )
 888         );
 889     }
 890 
 891     public function doDuplicate($data,$form) {
 892         if($obj = $this->dataObj()) {
 893             for($i = 0;$i < $data['Count'];$i++) {
 894                 $new = $obj->duplicate();
 895                 if(isset($data['Relations']) && $data['Relations'] == "1") {
 896                     if($has_manys = $obj->has_many()) {
 897                         foreach($has_manys as $name => $class) {
 898                             // get the owner relation name
 899                             if($has_ones = singleton($class)->has_one()) {
 900                                 if($ownerRelation = array_search($this->ctf->SourceClass(),$has_ones)) {
 901                                     $ownerID = $ownerRelation."ID";
 902                                     if($related_objects = $obj->$name()) {
 903                                         foreach($related_objects as $related_obj) {
 904                                             $o = $related_obj->duplicate(false);
 905                                             $o->$ownerID = $new->ID;
 906                                             $o->write();
 907                                         }
 908                                     }
 909                                 }
 910                                 else
 911                                     die(sprintf(_t('DataObjectManager.COULDNOTFINDRELATION','Could not find owner relation for class %s'),$this->ctf->SourceClass()));
 912                             }
 913                             else
 914                                 die(sprintf(_t('DataObjectManager.COULDNOTFINDRELATION','Could not find owner relation for class %s'),$this->ctf->SourceClass()));
 915                         }
 916                     }
 917                     if($many_manys = $obj->many_many()) {
 918                         foreach($many_manys as $name => $class) {
 919                             if($obj->$name()) {
 920                                 $new->$name()->setByIdList($obj->$name()->column());
 921                             }
 922                         }
 923                         $new->write();
 924                     }
 925                 }
 926             }
 927             $ret = "$i " . _t('DataObjectManager.DUPLICATESCREATED','duplicate(s) created');
 928             if(isset($data['Relations']) && $data['Relations'] == "1") $ret .= ", " . _t('DataObjectManager.WITHRELATIONS','with relations included');
 929             $form->sessionMessage($ret,'good');
 930         }
 931         else
 932             $form->sessionMessage(_t('DataObjectManager.ERRORDUPLICATING','There was an error duplicating the object.'),'bad');
 933         Director::redirectBack();
 934     }
 935 
 936 
 937     protected function getPrevID() {
 938         return $this->itemList[$this->currentIndex - 1];
 939     }
 940 
 941     protected function getNextID() {
 942         return $this->itemList[$this->currentIndex + 1];
 943     }
 944 
 945     function NextRecordLink() {
 946         if(!$this->itemList || $this->currentIndex == sizeof($this->itemList)-1) return false;
 947         return Controller::join_links($this->ctf->BaseLink() , '/item/' . $this->getNextID().'/edit')."?".$this->ctf->getQueryString();
 948     }
 949 
 950     function PrevRecordLink() {
 951         if(!$this->itemList || $this->currentIndex == 0) return false;
 952         return Controller::join_links($this->ctf->BaseLink() , '/item/' . $this->getPrevID().'/edit')."?".$this->ctf->getQueryString();
 953     }
 954 
 955     function HasPagination() {
 956         return $this->NextRecordLink() || $this->PrevRecordLink();
 957     }
 958 
 959     function HasDuplicate() {
 960         return $this->ctf->Can('duplicate');
 961     }
 962 
 963     function SingleTitle() {
 964         return $this->ctf->SingleTitle();
 965     }
 966 
 967     function DuplicateLink() {
 968         return Controller::join_links($this->ctf->BaseLink(),'/duplicate/'.$this->itemID);
 969     }
 970 
 971     function HasRelated() {
 972         $has_many = singleton($this->ctf->SourceClass())->has_many();
 973         return is_array($has_many) && !empty($has_many);
 974     }
 975 
 976 }
 977 
 978 class DataObjectManagerAction extends ViewableData {
 979     static $behaviour_to_js = array (
 980             'popup' => 'popup-button',
 981             'delete' => 'delete-link',
 982             'refresh' => 'refresh-button'
 983     );
 984 
 985     public $Title;
 986     public $Behaviour;
 987     public $ActionClass;
 988     public $Link;
 989     public $IconURL;
 990 
 991     public function __construct($title, $link, $behaviour = "popup", $icon = null, $class = null, $rel = null) {
 992         parent::__construct();
 993         $this->Title = $title;
 994         $this->Link = $link;
 995         $this->Behaviour = self::$behaviour_to_js[$behaviour];
 996         $this->IconURL = $icon;
 997         $this->ActionClass = $class;
 998         $this->Rel = $rel;
 999     }
1000 }
1001 
1002 class RussianUpLower {
1003     function str_to_upper($str) {
1004         return strtr($str,
1005                 "abcdefghijklmnopqrstuvwxyz".
1006                 "\xE0\xE1\xE2\xE3\xE4\xE5".
1007                 "\xb8\xe6\xe7\xe8\xe9\xea".
1008                 "\xeb\xeC\xeD\xeE\xeF\xf0".
1009                 "\xf1\xf2\xf3\xf4\xf5\xf6".
1010                 "\xf7\xf8\xf9\xfA\xfB\xfC".
1011                 "\xfD\xfE\xfF",
1012                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
1013                 "\xC0\xC1\xC2\xC3\xC4\xC5".
1014                 "\xA8\xC6\xC7\xC8\xC9\xCA".
1015                 "\xCB\xCC\xCD\xCE\xCF\xD0".
1016                 "\xD1\xD2\xD3\xD4\xD5\xD6".
1017                 "\xD7\xD8\xD9\xDA\xDB\xDC".
1018                 "\xDD\xDE\xDF");
1019     }
1020 
1021     function str_to_lower($str) {
1022         return strtr($str,
1023                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
1024                 "\xC0\xC1\xC2\xC3\xC4\xC5".
1025                 "\xA8\xC6\xC7\xC8\xC9\xCA".
1026                 "\xCB\xCC\xCD\xCE\xCF\xD0".
1027                 "\xD1\xD2\xD3\xD4\xD5\xD6".
1028                 "\xD7\xD8\xD9\xDA\xDB\xDC".
1029                 "\xDD\xDE\xDF",
1030                 "abcdefghijklmnopqrstuvwxyz".
1031                 "\xE0\xE1\xE2\xE3\xE4\xE5".
1032                 "\xb8\xe6\xe7\xe8\xe9\xea".
1033                 "\xeb\xeC\xeD\xeE\xeF\xf0".
1034                 "\xf1\xf2\xf3\xf4\xf5\xf6".
1035                 "\xf7\xf8\xf9\xfA\xfB\xfC".
1036                 "\xfD\xfE\xfF");
1037     }
1038 }
1039 
1040 class DOMUtil {
1041     public static function readable_list($array) {
1042         if(!is_array($array))
1043             return '';
1044         $and = _t('DataObjectManager.AND','and');
1045         switch(count($array)) {
1046             case 0:
1047                 return '';
1048             case 1:
1049             // This may not be a normal numerically-indexed array.
1050                 return reset($array);
1051             case 2:
1052                 return reset($array)." $and ".end($array);
1053             default:
1054                 $last = array_pop($array);
1055                 return implode(', ', $array).", $and $last";
1056         }
1057     }
1058 
1059     public static function readable_class($string) {
1060         /*
1061         // FIX Inxo
1062         $c = new RussianUpLower();
1063         $clss = $c->str_to_upper(trim($c->str_to_lower(ereg_replace('([A-Z])',' \\1',$string))));
1064         return $clss;
1065         */
1066         return ucwords(trim(strtolower(preg_replace('!([A-Z])!',' \\1',$string))));
1067     }
1068 
1069     /**
1070      * Translates a camel case string into a string with underscores (e.g. firstName -&gt; first_name)
1071      * @param    string   $str    String in camel case format
1072      * @return    string            $str Translated into underscore format
1073      */
1074     public static function to_underscore($str) {
1075         $str[0] = strtolower($str[0]);
1076         $func = function($c) { return "_" . strtolower($c[1]); };
1077         return preg_replace_callback('/([A-Z])/', $func, $str);
1078     }
1079 
1080     /**
1081      * Translates a string with underscores into camel case (e.g. first_name -&gt; firstName)
1082      * @param    string   $str                     String in underscore format
1083      * @param    bool     $capitalise_first_char   If true, capitalise the first char in $str
1084      * @return   string                              $str translated into camel caps
1085      */
1086     public static function to_camel_case($str, $capitalise_first_char = false) {
1087         if($capitalise_first_char) {
1088             $str[0] = strtoupper($str[0]);
1089         }
1090         $func = function($c) { return strtoupper($c[1]); };
1091         return preg_replace_callback('/_([a-z])/', $func, $str);
1092     }
1093 
1094 }
1095 
1096 
1097 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0