Version: current

      1 <?php
      2
      3 /**
      4  * Description of CustomMenuAdmin
      5  *
      6  * @author inxo, menedem
      7  */
      8 class CustomMenuAdmin extends LeftAndMain {
      9
     10     static $url_segment = 'menus';
     11     static $menu_title = 'Menus';
     12     static $menu_priority = 6;
     13     static $url_priority = 41;
     14     static $url_rule = '/$Action/$ID/$OtherID';
     15     static $tree_class = "CustomMenuHolder";
     16
     17     static function get_subsites() {
     18         $items = new DataObjectSet();
     19         $items->push(new ArrayData(array(
     20             'ID' => 0,
     21             'Title' => _t('CustomMenus.MainSubsite', 'Main Subsite'),
     22         )));
     23         if (class_exists('Subsite') && ($subsites = DataObject::get('Subsite'))) {
     24             foreach($subsites as $subsite) {
     25                 $items->push($subsite);
     26             }
     27         }
     28         return $items;
     29     }
     30
     31     function SiteTreeAsUL() {
     32         $this->generateDataTreeHints();
     33         $where = "";
     34         if (class_exists('Subsite') && ($subsite = Subsite::currentSubsite())) {
     35             $subsiteID = $subsite->ID;
     36             $where = "SubsiteID = {$subsiteID}";
     37         } else {
     38             $subsite = new ArrayData(array(
     39                 'ID' => 0,
     40                 'Title' => _t('CustomMenus.MainSubsite', 'Main Subsite'),
     41             ));
     42             $subsiteID = 0;
     43         }
     44         $subsite->Holders = DataObject::get('CustomMenuHolder', $where);
     45         return $this->customise(array(
     46             'Subsites' => $subsite
     47         ))->renderWith('SubsiteTreeAsUL');
     48     }
     49     /*
     50     public function changesubsite() {
     51         $id = $_REQUEST['SubsiteID'];
     52         Subsite::changeSubsite($id==-1 ? 0 : $id);
     53
     54         if(Director::is_ajax()) {
     55             $tree = $this->SubsiteTreeAsUL();
     56             $tree = ereg_replace('^[ \t\r\n]*<ul[^>]*>','', $tree);
     57             $tree = ereg_replace('</ul[^>]*>[ \t\r\n]*$','', $tree);
     58             return $tree;
     59         } else
     60             return array();
     61     }
     62     */
     63     /*
     64     public function SubsiteList() {
     65
     66         $list = $this->Subsites();
     67
     68         $currentSubsiteID = Subsite::currentSubsiteID();
     69
     70         //$currentSubsiteID = ($requestSubsiteID) ? $requestSubsiteID : Session::get('SubsiteID');
     71
     72         if($list->Count() > 1) {
     73             $output = '<select id="SubsitesMenuSelect">';
     74
     75             foreach($list as $subsite) {
     76                 $selected = $subsite->ID == $currentSubsiteID ? ' selected="selected"' : '';
     77
     78                 $output .= "\n<option value=\"{$subsite->ID}\"$selected>".htmlspecialchars($subsite->Title, ENT_QUOTES)."</option>";
     79             }
     80
     81             $output .= '</select>';
     82
     83             Requirements::javascript('custom_menu/javascript/CustomMenu_Subsites.js');
     84
     85             return $output;
     86         } else if($list->Count() == 1) {
     87             return $list->First()->Title;
     88         }
     89     }
     90     */
     91     public function init() {
     92         parent::init();
     93         Requirements::javascript('custom_menu/javascript/CustomMenu_right.js');
     94         Requirements::javascript('custom_menu/javascript/CustomMenu_left.js');
     95         Requirements::css('custom_menu/css/CustomMenu.css');
     96     }
     97
     98     /**
     99      * Basic action to display a blank pannel when the root node is selected
    100      * from the left sitetree.
    101      *
    102      * @return <type> false
    103      */
    104     public function root() {
    105         return false;
    106     }
    107
    108     /**
    109      * get_menus retrieves all CustomMenuHolder objects from the database,
    110      * which will be rendered in the left pain by the template.
    111      *
    112      * @return DataObjectSet
    113      */
    114     public function get_menus() {
    115         $result = DataObject::get('CustomMenuHolder');
    116         return $result;
    117     }
    118
    119     function Subsites() {
    120         $items = self::get_subsites();
    121         foreach($items as $item) {
    122             $item->Holders = DataObject::get('CustomMenuHolder', "SubsiteID = {$item->ID}");
    123         }
    124         return $items;
    125     }
    126
    127     public function EditForm() {
    128         // Include JavaScript to ensure HtmlEditorField works.
    129         HtmlEditorField::include_js();
    130         $form = $this->getEditForm();
    131         if ($form) {
    132             $form->disableDefaultAction();
    133             return $form;
    134         }
    135         return false;
    136     }
    137
    138     /**
    139      * Generate the editform, only if there is a URL ID available
    140      * @see cms/code/LeftAndMain#getEditForm($id)
    141      */
    142     function getEditForm() {
    143         $id = $this->currentPageID();
    144
    145         $holderID = $id;
    146         $itemID = false;
    147
    148         // проверяем $_POST перед проверкой currentPageID, чтобы работало при сабмите формы - тогда currentPageID неверный, тип формы приходится определять по данным $_POST (поле Type)
    149         if (isset($_POST['Type'])) {
    150             if ($_POST['Type'] == 'CustomMenuHolder') {
    151                 $holderID = $id;
    152                 $itemID = false;
    153             }
    154             if ($_POST['Type'] == 'CustomMenuItem') {
    155                 $holderID = false;
    156                 $itemID = $id;
    157             }
    158         } else {
    159             if (strpos($id, '-') !== false) {
    160                 $ids = explode('-', $id);
    161                 $holderID = (int)$ids[0];
    162                 $itemID = (int)$ids[1];
    163             }
    164         }
    165
    166         if ($itemID && ($currentItem = DataObject::get_by_id('CustomMenuItem', $itemID))) {
    167             $fields = $currentItem->getCMSFields();
    168             // учитываем родителя
    169             $fields->push(new HiddenField('ParentID'));
    170             $fields->push(new HiddenField('ID'));
    171             $fields->push(new HiddenField('Type', 'Type', 'CustomMenuItem'));
    172             $actions = new FieldSet(
    173                 new FormAction('doDeleteItem', _t('CustomMenus.FormActionDeleteItem', 'Delete Item')),
    174                 new FormAction('doUpdateItem', _t('CustomMenus.FormActionUpdateItem', 'Update Item'))
    175             );
    176             $form = new Form($this, "EditForm", $fields, $actions);
    177             $form->loadDataFrom($currentItem);
    178             return $form;
    179         }
    180
    181         if ($holderID && ($currentMenu = DataObject::get_by_id('CustomMenuHolder', $holderID))) {
    182             $fields = $currentMenu->getCMSFields();
    183             $fields->dataFieldByName('Pages')->setSourceFilter('ParentID = ' . $holderID);
    184             $fields->addFieldToTab('Root.Pages', new HiddenField('ClassName', 'CustomMenuItem'));
    185
    186             // учитываем подсайты
    187             $fields->push(new HiddenField('SubsiteID'));
    188             $fields->push(new HiddenField('Type', 'Type', 'CustomMenuHolder'));
    189
    190             if (Director::isDev() && Member::currentUser()->isAdmin()) {
    191                 $actions = new FieldSet(
    192                                 new FormAction('doDeleteMenu', _t('CustomMenus.FormActionDelete', 'Delete Menu')),
    193                                 new FormAction('doUpdateMenu', _t('CustomMenus.FormActionUpdate', 'Update Menu'))
    194                 );
    195             } else {
    196                 $fields->removeByName('Main');
    197                 $actions = new FieldSet(
    198                     new LabelField('CanNotEdit', '') // костыль, чтоб не выводить кнопок, но они не считались пустыми и обновлялись на frontend
    199                                 //new FormAction('doUpdateMenu', _t('CustomMenus.FormActionUpdate', 'Update Menu'))
    200                 );
    201             }
    202             $form = new Form($this, "EditForm", $fields, $actions);
    203             $form->loadDataFrom($currentMenu);
    204             return $form;
    205
    206         }
    207     }
    208
    209     function leftMenuForm() {
    210         if (Director::isDev() && Member::currentUser()->isAdmin()) {
    211             // Create form fields
    212             $fields = new FieldSet(
    213                             new HiddenField('ID', 'id#', 'new'),
    214                             new HiddenField('SubsiteID'),
    215                             new HiddenField('HolderID'),
    216                             new HiddenField('ItemID')
    217             );
    218             /*
    219             $subsites = self::get_subsites();
    220             if ($subsites->Count() == 1) {
    221                 $fields->push(new HiddenField('SubsiteID'));
    222             } else {
    223                 $fields->push(new DropdownField('SubsiteID', 'Подсайт', $subsites->map()));
    224             }
    225             */
    226             $actions = new FieldSet(
    227                             new FormAction('doCreateMenu', _t('CustomMenus.CreateMenu', 'Create Menu'))
    228             );
    229             $form = new Form($this, "LeftMenuForm", $fields, $actions);
    230             return $form;
    231         }
    232         return false;
    233     }
    234
    235     function doUpdateMenu($data, $form) {
    236         $id = $data['ID'];
    237
    238         $record = DataObject::get_by_id("CustomMenuHolder", $id);
    239         $record->Status = "Saved (update)";
    240         $form->saveInto($record);
    241
    242         if ($record->write()) {
    243             FormResponse::status_message(_t('CustomMenus.UpdateSuccess', 'Updated Menu'), 'good');
    244             FormResponse::update_status($record->Status);
    245             FormResponse::set_node_title($id, $record->Title);
    246             FormResponse::get_page($id);
    247         } else {
    248             FormResponse::status_message(_t('CustomMenus.UpdateFail', 'Update Failed'), 'bad');
    249         }
    250
    251         return FormResponse::respond();
    252     }
    253
    254     function doDeleteMenu($data, $form) {
    255         if (Director::isDev() && Member::currentUser()->isAdmin()) {
    256             $id = $data['ID'];
    257
    258             $record = DataObject::get_by_id("CustomMenuHolder", $id);
    259             $record->delete();
    260
    261             FormResponse::add($this->deleteTreeNodeJS($record));
    262             FormResponse::status_message(_t('CustomMenus.DeleteSuccess', 'Deleted Menu'), 'good');
    263         } else {
    264             FormResponse::status_message(_t('CustomMenus.DeleteFail', 'Delete Failed'), 'bad');
    265         }
    266         return FormResponse::respond();
    267     }
    268
    269     function doUpdateItem($data, $form) {
    270         $id = $data['ID'];
    271
    272         $record = DataObject::get_by_id("CustomMenuItem", $id);
    273         $record->Status = "Saved (update)";
    274         $form->saveInto($record);
    275
    276         if ($record->ParentItemID) {
    277             $parentID = $record->ParentItemID;
    278         } else {
    279             $parentID = $record->ParentID;
    280         }
    281
    282         if ($record->write()) {
    283             FormResponse::status_message(_t('CustomMenus.UpdateSuccess', 'Updated Menu'), 'good');
    284             FormResponse::update_status($record->Status);
    285             FormResponse::set_node_title("{$parentID}-{$id}", $record->Title);
    286             $response = <<<JS
    287                 $('Form_EditForm').getPageFromServer('{$parentID}-{$id}');
    288 JS;
    289             FormResponse::add($response);
    290
    291         } else {
    292             FormResponse::status_message(_t('CustomMenus.UpdateFail', 'Update Failed'), 'bad');
    293         }
    294
    295         return FormResponse::respond();
    296     }
    297
    298     function doDeleteItem($data, $form) {
    299         if (Director::isDev() && Member::currentUser()->isAdmin()) {
    300             $id = $data['ID'];
    301             $record = DataObject::get_by_id("CustomMenuItem", $id);
    302             if ($record->ParentItemID) {
    303                 $parentID = $record->ParentItemID;
    304             } else {
    305                 $parentID = $record->ParentID;
    306             }
    307             $record->delete();
    308
    309             FormResponse::status_message(_t('CustomMenus.DeleteSuccess', 'Deleted Menu'), 'good');
    310             $response = <<<JS
    311                 var st = $('sitetree');
    312                 var node = st.getTreeNodeByIdx('{$parentID}-{$id}');
    313                 if( node && node.parentTreeNode ) node.parentTreeNode.removeTreeNode( node );
    314                 $('Form_EditForm').close(); //IfSetTo('{$parentID}-{$id}');
    315 JS;
    316             FormResponse::add($response);
    317         } else {
    318             FormResponse::status_message(_t('CustomMenus.DeleteFail', 'Delete Failed'), 'bad');
    319         }
    320         return FormResponse::respond();
    321     }
    322
    323     function doCreateMenu($data, $form) {
    324         if (Director::isDev() && Member::currentUser()->isAdmin()) {
    325             if (isset($data['ItemID']) && ($itemID = (int)$data['ItemID'])) {
    326                 if ($item = DataObject::get_by_id('CustomMenuItem', $itemID)) {
    327                     $subItem = new CustomMenuItem();
    328                     $subItem->Title = 'New SubItem';
    329                     $subItem->ParentItemID = $item->ID;
    330                     $subItem->write();
    331                     FormResponse::status_message(_t('CustomMenus.CreateSubItemSuccess', 'Created SubItem'), 'good');
    332
    333                     $response = <<<JS
    334                     var newNode = $('sitetree').createTreeNode('{$subItem->ParentItemID}-{$subItem->ID}', '{$subItem->Title}', 'subitem');
    335                     $('sitetree').appendTreeNode(newNode);
    336                     $('sitetree').setNodeParentID('{$subItem->ParentItemID}-{$subItem->ID}', '{$item->ParentID}-{$subItem->ParentItemID}');
    337                     newNode.setAttribute("itemclass",'subitem');
    338                     $('sitetree').changeCurrentTo(newNode);
    339                     $('Form_EditForm').getPageFromServer('{$subItem->ParentItemID}-{$subItem->ID}');
    340 JS;
    341                     FormResponse::add($response);
    342
    343                 }
    344             } elseif (isset($data['HolderID']) && ($holderID = (int)$data['HolderID'])) {
    345                 if ($holder = DataObject::get_by_id('CustomMenuHolder', $holderID)) {
    346                     $item = new CustomMenuItem();
    347                     $item->Title = 'New Item';
    348                     $item->ParentID = $holder->ID;
    349                     $item->write();
    350                     FormResponse::status_message(_t('CustomMenus.CreateItemSuccess', 'Created Item'), 'good');
    351
    352                     $response = <<<JS
    353                     var newNode = $('sitetree').createTreeNode('{$item->ParentID}-{$item->ID}', '{$item->Title}', 'item');
    354                     $('sitetree').appendTreeNode(newNode);
    355                     $('sitetree').setNodeParentID('{$item->ParentID}-{$item->ID}', '{$item->ParentID}');
    356                     newNode.setAttribute("itemclass",'item');
    357                     $('sitetree').changeCurrentTo(newNode);
    358                     $('Form_EditForm').getPageFromServer('{$item->ParentID}-{$item->ID}');
    359 JS;
    360                     FormResponse::add($response);
    361
    362                 }
    363             } else {
    364                 $menu = new CustomMenuHolder();
    365                 $menu->Title = 'New Menu';
    366                 $menu->Slug = "new-menu";
    367                 $menu->Child = "new-menu";
    368                 if (isset($data['SubsiteID'])) {
    369                     $menu->SubsiteID = (int)$data['SubsiteID'];
    370                 }
    371                 $menu->write();
    372                 FormResponse::status_message(_t('CustomMenus.CreateSuccess', 'Created Menu'), 'good');
    373
    374                 $response = <<<JS
    375                 var newNode = $('sitetree').createTreeNode('{$menu->ID}', '{$menu->Title}', 'holder');
    376                 $('sitetree').appendTreeNode(newNode);
    377                 $('sitetree').setNodeParentID('{$menu->ID}', 'subsite-{$menu->SubsiteID}');
    378                 newNode.setAttribute("itemclass",'holder');
    379                 $('sitetree').changeCurrentTo(newNode);
    380                 $('Form_EditForm').getPageFromServer('{$menu->ID}');
    381 JS;
    382                 FormResponse::add($response);
    383
    384             }
    385         } else {
    386             FormResponse::status_message(_t('CustomMenus.CreateFail', 'Creation Failed'), 'bad');
    387         }
    388         return FormResponse::respond();
    389     }
    390
    391     // список WebylonWingetArea со списком возможных создаваемых виджетов
    392     public function generateDataTreeHints() {
    393         $def = array();
    394         $def['Root'] = false;
    395         $def['subsite'] = array();
    396         $def['holder'] = array();
    397         $def['item'] = array();
    398         $def['subitem'] = array();
    399
    400         $def['subsite']['allowedChildren'] = false;
    401         $def['holder']['allowedChildren'] = array();
    402         $def['holder']['allowedChildren'][] = 'item';
    403         $def['holder']['allowedChildren'][] = 'subitem';
    404         $def['item']['allowedChildren'] = array();
    405         $def['item']['allowedChildren'][] = 'item';
    406         $def['item']['allowedChildren'][] = 'subitem';
    407         $def['subitem']['allowedChildren'] = false;
    408
    409         /*
    410         $def['subsite']['PossibleWidgets'] = false;
    411         $def['holder']['PossibleWidgets'] = array();
    412         $def['holder']['PossibleWidgets'][] = array('class' => 'item', 'title' => 'item');
    413         $def['holder']['PossibleWidgets'][] = array('class' => 'subitem', 'title' => 'subitem');
    414         $def['item']['PossibleWidgets'] = array();
    415         $def['item']['PossibleWidgets'][] = array('class' => 'subitem', 'title' => 'subitem');
    416         $def['subitem']['PossibleWidgets'] = false;
    417         */
    418
    419
    420         /*
    421         $objList = $this->getObjList(); //DataObject::get($this->stat('parent_tree_class'));
    422         if ($objList) {
    423             foreach ($objList as $area) {
    424                 $isHiddenArea = SiteConfigWidgets::is_area_readonly($area->TechName);
    425                 if (isset($def[$area->TechName]) || $isHiddenArea) {
    426                     continue;
    427                 }
    428                 $widgetClass = $area::$widgetClass;
    429                 $allWidgets = ClassInfo::subclassesFor($widgetClass);
    430                 unset($allWidgets[0]);
    431                 foreach($allWidgets as $widget) {
    432                     $obj = singleton($widget);
    433                     if ($obj->canCreate($area)) {
    434                         $line = array();
    435                         $line['class'] = $widget;
    436                         $line['title'] = sprintf(_t('WidgetAdmin.CreateLine', 'Widget "%s"'), $obj->i18n_singular_name());
    437                         //singleton($widget)->i18n_singular_name();//_t('WidgetsAdmin.Title_'.$allWidget);
    438                         $def[$area->TechName]['PossibleWidgets'][] = $line;
    439                         $def[$area->ClassName]['allowedChildren'][] = $widget;
    440                         $def[$area->TechName]['CanDrag'] = $isHiddenArea;
    441                         $def[$widget]['allowedChildren'][] = false;
    442                     }
    443                 }
    444             }
    445         }
    446         */
    447         $def['Root']['allowedChildren'][] = false;
    448         // Put data hints into a script tag at the top
    449         Requirements::customScript("siteTreeHints = " . $this->jsDeclaration($def) . ";");
    450     }
    451
    452     /**
    453      * Return a javascript instanciation of this array
    454      */
    455     protected function jsDeclaration($array) {
    456         if(is_array($array)) {
    457             $object = false;
    458             foreach(array_keys($array) as $key) {
    459                 if(!is_numeric($key)) {
    460                     $object = true;
    461                     break;
    462                 }
    463             }
    464
    465             if($object) {
    466                 foreach($array as $k => $v) {
    467                     $parts[] = "$k : " . $this->jsDeclaration($v);
    468                 }
    469                 return " {\n " . implode(", \n", $parts) . " }\n";
    470             } else {
    471                 foreach($array as $part) $parts[] = $this->jsDeclaration($part);
    472                 return " [ " . implode(", ", $parts) . " ]\n";
    473             }
    474         } else {
    475             return "'" . addslashes($array) . "'";
    476         }
    477     }
    478
    479     public function ajaxupdatesort() {
    480         $className = 'CustomMenuItem';
    481         $counter = 0;
    482         $js = '';
    483         $_REQUEST['ajax'] = 1;
    484
    485         if(is_array($_REQUEST['ID'])) {
    486             $movedNodeID = explode('-', $_REQUEST['MovedNodeID']);
    487             $movedNodeID = $movedNodeID[1];
    488             $movedNode = DataObject::get_by_id($className, $movedNodeID);
    489             foreach($_REQUEST['ID'] as $id) {
    490                 $id = explode('-', $id);
    491                 $id = $id[1];
    492                 if($id == $movedNode->ID) {
    493                     $movedNode->SortOrder = ++$counter;
    494                     $movedNode->Status = "Saved (update)";
    495                     $movedNode->write();
    496
    497                     $title = Convert::raw2js($movedNode->Title);
    498                     $js .="$('sitetree').setNodeTitle($movedNode->ID, \"$title\");\n";
    499
    500                 // Nodes that weren't "actually moved" shouldn't be registered as having been edited; do a direct SQL update instead
    501                 } else if(is_numeric($id)) {
    502                     ++$counter;
    503                     DB::query("UPDATE CustomMenuItem SET \"SortOrder\" = $counter WHERE \"ID\" = '$id'");
    504                 }
    505             }
    506             FormResponse::status_message(_t('LeftAndMain.SAVED'), 'good');
    507         } else {
    508             FormResponse::error(_t('LeftAndMain.REQUESTERROR',"Error in request"));
    509         }
    510         return FormResponse::respond();
    511     }
    512
    513     public function ajaxupdateparent() {
    514         $js = '';
    515         $className = 'CustomMenuItem';
    516         $itemClass = 'item';
    517         $requestID = $_REQUEST['ID'];
    518         $id = explode('-', $requestID);
    519         $id = $id[1];
    520         $parentID = $_REQUEST['ParentID'];
    521         $parentField = 'ParentID';
    522         $oldParentField = 'ParentItemID';
    523         if (strpos($parentID, '-') !== false) {
    524             $parentID = explode('-', $parentID);
    525             $parentID = $parentID[1];
    526             $parentField = 'ParentItemID';
    527             $oldParentField = 'ParentID';
    528             $itemClass = 'subitem';
    529         }
    530         if($parentID == 'root'){
    531             $parentID = 0;
    532         }
    533         $_REQUEST['ajax'] = 1;
    534
    535         if(is_numeric($id) && is_numeric($parentID) && $id != $parentID) {
    536             $node = DataObject::get_by_id($className, $id);
    537             if($node){
    538                 $node->{$parentField} = $parentID;
    539                 $node->{$oldParentField} = 0;
    540                 $node->write();
    541                 $response = <<<JS
    542
    543                 var st = $('sitetree');
    544                 var node = st.getTreeNodeByIdx('{$requestID}');
    545                 node.setAttribute("itemclass",'{$itemClass}');
    546                 node.setAttribute("class",'{$itemClass}');
    547                 node.setAttribute("areaclass",'{$itemClass}');
    548                 node.setAttribute("id",'record-{$parentID}-{$node->ID}');
    549 JS;
    550                 FormResponse::add($response);
    551                 FormResponse::status_message(_t('LeftAndMain.SAVED','saved'), 'good');
    552             } else {
    553                 FormResponse::status_message(_t('LeftAndMain.PLEASESAVE',"Please Save Page: This page could not be upated because it hasn't been saved yet."),"good");
    554             }
    555             return FormResponse::respond();
    556         } else {
    557             return FormResponse::respond();
    558             user_error("Error in ajaxupdateparent request; id=$id, parentID=$parentID", E_USER_ERROR);
    559         }
    560     }
    561 }
    562

[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. -