Version: current

      1 <?php
      2
      3 /**
      4  * @class WidgetAdmin - админка для виджетов
      5  *
      6  * @package widgets
      7  * @author  menedem
      8  */
      9 class WidgetAdmin extends LeftAndMain {
     10
     11     static $url_segment = 'widgets';
     12     static $url_rule = '/$Action/$ID';
     13     static $menu_title = 'Widgets';
     14     static $parent_tree_class = 'WebylonWidgetArea';
     15     static $tree_class = 'WebylonWidget';
     16
     17     /**
     18      * @return boolean
     19      */
     20     function IsTranslatableEnabled() {
     21         return Object::has_extension('SiteConfig', 'Translatable');
     22     }
     23
     24     /**
     25      * Returns all languages with languages already used appearing first.
     26      * Called by the SSViewer when rendering the template.
     27      */
     28     function LangSelector() {
     29         $member = Member::currentUser();
     30         $dropdown = new LanguageDropdownField(
     31             'LangSelector',
     32             'Language',
     33             array(),
     34             'SiteTree',
     35             'Locale-English',
     36             singleton('SiteTree')
     37         );
     38         $dropdown->setValue(Translatable::get_current_locale());
     39         return $dropdown;
     40     }
     41
     42
     43     public function init() {
     44         parent::init();
     45         Requirements::javascript("widgets/javascript/WidgetAdmin_left.js");
     46         Requirements::javascript("widgets/javascript/WidgetAdmin_right.js");
     47     }
     48
     49     function getObjList() {
     50         $sc = SiteConfig::current_site_config();
     51         return $sc->getActiveWidgetAreas();
     52     }
     53
     54     /**
     55      * Send the SiteTree for RandomLinks as a Unordered List
     56      *
     57      * @return String - An HTML UL made up of LIs of the titles of the RandomLinks
     58      */
     59     public function SiteTreeAsUL() {
     60         $this->generateDataTreeHints();
     61         $siteTree = "";
     62         $objList = $this->getObjList(); //DataObject::get($this->stat('parent_tree_class'));
     63         $currentAreaID = Session::get('CurrentWidgetArea');
     64         $currentWidgetID = Session::get('CurrentWidget');
     65
     66         if ($objList) {
     67             foreach ($objList as $area) {
     68                 $subObjList = $area->Widgets();
     69
     70                 $siteTree .= '<li id="record-' . $area->ID
     71                     . '" class="Folder ' . $area->class
     72                         . ($area->Locked ? ' nodelete' : '')
     73                         . (SiteConfigWidgets::is_area_readonly($area->TechName) ? ' nochildren' : '')
     74                         . ($subObjList ? ' children' : '')
     75                         . ($area->ID == $currentAreaID ? ' current' : '')
     76                     . '" itemclass="' . $area->class
     77                     . '"  areaclass="' . $area->TechName .
     78                     '" ' . (SiteConfigWidgets::is_area_readonly($area->TechName) ? 'readonly="true"' : '') . '>'
     79                     . '<a href="admin/' . $this->stat('url_segment').'/show/'. $area->ID . '" >' . _t('WebylonWidgetArea.Title_' . $area->TechName, $area->TechName) . '('.$area->class.')</a>';
     80
     81                 if ($subObjList) {
     82                     $subSiteTree = '';
     83                     foreach ($subObjList as $widget) {
     84                         // пропускаем скрытые виджеты
     85                         if (WebylonWidget::is_hidden_widget($widget->class)) {
     86                             continue;
     87                         }
     88                         $widgetID = $area->ID . '-' . $widget->ID;
     89                         $subSiteTree .= '<li id="record-' . $widgetID
     90                             . '" class="' . $widget->class
     91                                 . ($widget->Locked ? ' nodelete' : '')
     92                                 . ($widget->ID == $currentWidgetID ? ' current' : '')
     93                             . '" itemclass="' . $widget->class
     94                             . '" areaclass="' . $area->TechName
     95                             . '" ' . (SiteConfigWidgets::is_area_readonly($area->TechName) ? 'readonly="true"' : '').'>'
     96                             . '<a class="' . $widget->class . '" href="admin/' . $this->stat('url_segment').'/show/'. $widgetID . '" title="' . _t('WidgetAdmin.WIDGETTYPE','Widget type: ') . $widget->class.'">' . $widget->Title . '</a></li>';
     97                     }
     98                     $siteTree .= '<ul class="area_children'.(SiteConfigWidgets::is_area_readonly($area->TechName) ? ' nochildren' : '') . '" style="padding-left: 16px;" '.(SiteConfigWidgets::is_area_readonly($area->TechName) ? 'readonly="true"' : '').'>' . $subSiteTree . '</ul>';
     99                 }
    100                 $siteTree .= '</li>';
    101
    102             }
    103         }
    104         $siteTree = '<li id="record-0" class="Root nodelete" readonly="true"><a href="#">'. _t('Widgets.SiteTreeTitle', 'Виджеты') .'</a><ul class="" readonly="true">' . $siteTree . '</ul></li>';
    105
    106         if (!$this->isAjax()) {
    107             return '<ul id="sitetree" class="tree">'
    108             //. '<li id="record-0" class="Root nodelete">'
    109             //. '<strong>ВСЕ РАЙОНЫ</strong></li>'
    110             . $siteTree . '</ul>';
    111         } else {
    112             return $siteTree;
    113         }
    114     }
    115
    116     /**
    117      * Генерирует форму для отображения вопросов
    118      *
    119      * @return Form
    120      */
    121
    122     function getEditForm() {
    123
    124         // 2 варианта: переданы WidgetId и ParentID и просто id
    125         // FIXME сделать рефакторинг!!!
    126         $req = $this->getRequest();
    127         if ($widgetID = $req->requestVar('WidgetID')) {
    128             $id = "1-" . $widgetID;
    129         }
    130         else {
    131             // WidgetArea
    132             $id = $this->currentPageID();
    133         }
    134         if (!$id)
    135             return false;
    136
    137         $widgetID = 0;
    138         if (strpos($id, '-') !== false) {
    139             $ids = explode('-', $id);
    140             $widgetID = $ids[1];
    141             //Widget
    142             $widget = DataObject::get_by_id($this->stat('tree_class'), $widgetID);
    143             if ($widget) {
    144                 Session::set('CurrentWidgetArea', $widget->ParentID);
    145                 Session::set('CurrentWidget', $widget->ID);
    146                 $fields = $widget->getCMSFields();
    147                 $fields->replaceField('ParentID', new HiddenField('ParentID'));
    148                 $fields->push(new HiddenField('WidgetID', 'WidgetID', $widget->ID));
    149                 $fields->push(new HiddenField('ID', 'ID', $widget->ID));
    150
    151                 $actions = $widget->getCMSActions();
    152                 $form = new Form($this, "EditForm", $fields, $actions);
    153                 $form->disableSecurityToken();
    154                 $form->loadDataFrom($widget);
    155                 if (SiteConfigWidgets::is_area_readonly($widget->Parent()->TechName)) {
    156                     $form->makeReadonly();
    157                 }
    158                 return $form;
    159             }
    160         }
    161         elseif ($widgetArea = DataObject::get_by_id($this->stat('parent_tree_class'), $id)) {
    162             Session::set('CurrentWidgetArea', $widgetArea->ID);
    163             // FIXME форма создания виджета с выбором класса или хоты бы фраза как осздать виджет
    164             $fields = new FieldSet();
    165             $fields->push(new HiddenField('ID', 'ID', $widgetArea->ID));
    166             $actions = new FieldSet(
    167             );
    168             $form = new Form($this, "EditForm", $fields, $actions);
    169             $form->disableSecurityToken();
    170             return $form;
    171         }
    172         return false;
    173     }
    174
    175
    176     function save($data, $form) {
    177         $id = (isset($data['WidgetID'])) ? (int)$data['WidgetID'] : 0;
    178         $parentID = (isset($data['ParentID'])) ? (int)$data['ParentID'] : 0;
    179
    180         $record = DataObject::get_by_id($this->stat('tree_class'), $id);
    181         if ($record) {
    182             $form->saveInto($record, true);
    183         }
    184         if ($record->write()) {
    185             FormResponse::status_message(_t('Widgets.SaveSuccess', 'Widget saved'), 'good');
    186             FormResponse::set_node_title("{$parentID}-{$id}", $record->Title);
    187             //FormResponse::get_page("{$parentID}-{$id}");
    188
    189             $response = <<<JS
    190                 var st = $('sitetree');
    191                 var node = st.getTreeNodeByIdx('{$parentID}-{$id}');
    192                 if( node ) node.getPageFromServer('{$parentID}-{$id}');
    193 JS;
    194             FormResponse::add($response);
    195
    196         } else {
    197             FormResponse::status_message(_t('Widgets.SaveFail', 'Save Failed'), 'bad');
    198         }
    199         return FormResponse::respond();
    200     }
    201
    202     function doDeleteWidget($data, $form) {
    203
    204         $id = (isset($data['WidgetID'])) ? (int)$data['WidgetID'] : 0;
    205         $parentID = (isset($data['ParentID'])) ? (int)$data['ParentID'] : 0;
    206
    207         DataObject::delete_by_id($this->stat('tree_class'), $id);
    208         FormResponse::status_message(_t('Widgets.DeleteSuccess', 'Widget deleted'), 'good');
    209         $response = <<<JS
    210                 var st = $('sitetree');
    211                 var node = st.getTreeNodeByIdx('{$parentID}-{$id}');
    212                 if( node && node.parentTreeNode ) node.parentTreeNode.removeTreeNode( node );
    213                 $('Form_EditForm').close(); //IfSetTo('{$parentID}-{$id}');
    214 JS;
    215         FormResponse::add($response);
    216
    217         return FormResponse::respond();
    218     }
    219
    220     // Форма добавления виджетов
    221     function AddWidgetOptionsForm() {
    222         $fields = new FieldSet(
    223             new HiddenField("ParentID")
    224         );
    225
    226         $pageTypes = array();
    227         $currentWidgetArea = false;
    228         if (Session::get('CurrentWidgetArea') && ($currentWidgetArea = DataObject::get_by_id($this->stat('parent_tree_class'), (int)Session::get('CurrentWidgetArea')))) {
    229             $fields->push(new HiddenField("AreaID", "AreaID", $currentWidgetArea->ID));
    230         }
    231         $widgetClass = false;
    232         if ($currentWidgetArea) {
    233             $widgetClass = $currentWidgetArea::$widgetClass;
    234             if (!SiteConfigWidgets::is_area_readonly($currentWidgetArea->TechName)) {
    235                 $allWidgets = SiteConfigWidgets::get_allowed_area_widgets($currentWidgetArea);
    236                 foreach ($allWidgets as $widget) {
    237                     $obj = singleton($widget);
    238                     if ($obj->canCreate($currentWidgetArea)) {
    239                         $pageTypes[$widget] = sprintf(_t('WidgetAdmin.CreateLine', 'Widget "%s"'), $obj->i18n_singular_name());
    240                     }
    241                 }
    242             }
    243         }
    244         $fields->push(new DropdownField("WidgetType", "", $pageTypes));
    245         $actions = new FieldSet(
    246             new FormAction("addwidget", _t('CMSMain.GO',"Go"))
    247         );
    248
    249         return new Form($this, "AddWidgetOptionsForm", $fields, $actions);
    250     }
    251
    252     function addwidget($data, $form) {
    253         if (isset($data['WidgetType']) && isset($data['AreaID'])) {
    254             $widgetClass = $data['WidgetType'];
    255             $widget = new $widgetClass();
    256             $widget->ParentID = (int)$data['AreaID'];
    257             if ($widget->write()) {
    258                 FormResponse::status_message(_t('Widgets.CreateSuccess', 'Widget created'), 'good');
    259
    260                 $response = <<<JS
    261                     var newNode = $('sitetree').createTreeNode('{$widget->ParentID}-{$widget->ID}', '{$widget->Title}', '{$widgetClass}');
    262                     $('sitetree').appendTreeNode(newNode);
    263                     $('sitetree').setNodeParentID('{$widget->ParentID}-{$widget->ID}', '{$widget->ParentID}');
    264                     newNode.setAttribute("itemclass",'{$widgetClass}');
    265                     newNode.setAttribute("areaclass",'{$widget->Parent()->TechName}');
    266                     $('sitetree').changeCurrentTo(newNode);
    267                     $('Form_EditForm').getPageFromServer('{$widget->ParentID}-{$widget->ID}');
    268 JS;
    269
    270                 FormResponse::add($response);
    271             }
    272
    273         } else {
    274             FormResponse::status_message(_t('Widgets.BadWidgetArea', 'Bad widget area'), 'bad');
    275
    276         }
    277         return FormResponse::respond();
    278
    279     }
    280
    281     public function EditForm() {
    282         // Include JavaScript to ensure HtmlEditorField works.
    283         HtmlEditorField::include_js();
    284         $form = $this->getEditForm();
    285         if ($form) {
    286             $form->disableDefaultAction();
    287             return $form;
    288         }
    289         return false;
    290     }
    291
    292     // список WebylonWingetArea со списком возможных создаваемых виджетов
    293     public function generateDataTreeHints() {
    294         $def['Root'] = false;
    295
    296         $objList = $this->getObjList(); //DataObject::get($this->stat('parent_tree_class'));
    297         if ($objList) {
    298             foreach ($objList as $area) {
    299                 $isHiddenArea = SiteConfigWidgets::is_area_readonly($area->TechName);
    300                 if (isset($def[$area->TechName]) || $isHiddenArea) {
    301                     continue;
    302                 }
    303                 $widgetClass = $area::$widgetClass;
    304                 $allWidgets = ClassInfo::subclassesFor($widgetClass);
    305                 unset($allWidgets[0]);
    306                 foreach($allWidgets as $widget) {
    307                     $obj = singleton($widget);
    308                     if ($obj->canCreate($area)) {
    309                         $line = array();
    310                         $line['class'] = $widget;
    311                         $line['title'] = sprintf(_t('WidgetAdmin.CreateLine', 'Widget "%s"'), $obj->i18n_singular_name());
    312                         //singleton($widget)->i18n_singular_name();//_t('WidgetsAdmin.Title_'.$allWidget);
    313                         $def[$area->TechName]['PossibleWidgets'][] = $line;
    314                         $def[$area->ClassName]['allowedChildren'][] = $widget;
    315                         $def[$area->TechName]['CanDrag'] = $isHiddenArea;
    316                         $def[$widget]['allowedChildren'][] = false;
    317                     }
    318                 }
    319             }
    320         }
    321         $def['Root']['allowedChildren'][] = false;
    322         // Put data hints into a script tag at the top
    323         Requirements::customScript("siteTreeHints = " . $this->jsDeclaration($def) . ";");
    324     }
    325
    326     /**
    327      * Return a javascript instanciation of this array
    328      */
    329     protected function jsDeclaration($array) {
    330         if(is_array($array)) {
    331             $object = false;
    332             foreach(array_keys($array) as $key) {
    333                 if(!is_numeric($key)) {
    334                     $object = true;
    335                     break;
    336                 }
    337             }
    338
    339             if($object) {
    340                 foreach($array as $k => $v) {
    341                     $parts[] = "$k : " . $this->jsDeclaration($v);
    342                 }
    343                 return " {\n " . implode(", \n", $parts) . " }\n";
    344             } else {
    345                 foreach($array as $part) $parts[] = $this->jsDeclaration($part);
    346                 return " [ " . implode(", ", $parts) . " ]\n";
    347             }
    348         } else {
    349             return "'" . addslashes($array) . "'";
    350         }
    351     }
    352
    353     public function ajaxupdatesort() {
    354         $className = $this->stat('tree_class');
    355         $counter = 0;
    356         $js = '';
    357         $_REQUEST['ajax'] = 1;
    358
    359         if (!Permission::check('SITETREE_REORGANISE') && !Permission::check('ADMIN')) {
    360             FormResponse::status_message(_t('LeftAndMain.CANT_REORGANISE',"You do not have permission to rearange the site tree. Your change was not saved."),"bad");
    361             return FormResponse::respond();
    362         }
    363
    364         if(is_array($_REQUEST['ID'])) {
    365             $movedNodeID = explode('-', $_REQUEST['MovedNodeID']);
    366             $movedNodeID = $movedNodeID[1];
    367             $movedNode = DataObject::get_by_id($className, $movedNodeID);
    368             foreach($_REQUEST['ID'] as $id) {
    369                 $id = explode('-', $id);
    370                 $id = $id[1];
    371                 if($id == $movedNode->ID) {
    372                     $movedNode->Sort = ++$counter;
    373                     $movedNode->Status = "Saved (update)";
    374                     $movedNode->write();
    375
    376                     $title = Convert::raw2js($movedNode->CMSTitle());
    377                     $js .="$('sitetree').setNodeTitle($movedNode->ID, \"$title\");\n";
    378
    379                 // Nodes that weren't "actually moved" shouldn't be registered as having been edited; do a direct SQL update instead
    380                 } else if(is_numeric($id)) {
    381                     ++$counter;
    382                     DB::query("UPDATE Widget SET \"Sort\" = $counter WHERE \"ID\" = '$id'");
    383                 }
    384             }
    385             FormResponse::status_message(_t('LeftAndMain.SAVED'), 'good');
    386         } else {
    387             FormResponse::error(_t('LeftAndMain.REQUESTERROR',"Error in request"));
    388         }
    389
    390         return FormResponse::respond();
    391     }
    392
    393     public function ajaxupdateparent() {
    394         $id = explode('-', $_REQUEST['ID']);
    395         $id = $id[1];
    396         $parentID = $_REQUEST['ParentID'];
    397         if($parentID == 'root'){
    398             $parentID = 0;
    399         }
    400         $_REQUEST['ajax'] = 1;
    401
    402         if (!Permission::check('SITETREE_REORGANISE') && !Permission::check('ADMIN')) {
    403             FormResponse::status_message(_t('LeftAndMain.CANT_REORGANISE',"You do not have permission to rearange the site tree. Your change was not saved."),"bad");
    404             return FormResponse::respond();
    405         }
    406
    407         if(is_numeric($id) && is_numeric($parentID) && $id != $parentID) {
    408             $node = DataObject::get_by_id($this->stat('tree_class'), $id);
    409             if($node){
    410                 if(!$node->canEdit() || ($node->hasMethod('checkDevPermisson') && !$node->checkDevPermisson(null,'canReorder'))){
    411                     return Security::permissionFailure($this);
    412                 }
    413                 $node->ParentID = $parentID;
    414                 $node->write();
    415                 FormResponse::status_message(_t('LeftAndMain.SAVED','saved'), 'good');
    416             }else{
    417                 FormResponse::status_message(_t('LeftAndMain.PLEASESAVE',"Please Save Page: This page could not be upated because it hasn't been saved yet."),"good");
    418             }
    419
    420
    421             return FormResponse::respond();
    422         } else {
    423             user_error("Error in ajaxupdateparent request; id=$id, parentID=$parentID", E_USER_ERROR);
    424         }
    425     }
    426
    427 }
    428

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