Version: current

      1 <?php
      2 /**
      3  * Базовый класс для виджетов
      4  *
      5  * @package widgets
      6  * @author  menedem
      7  */
      8 class WebylonWidget extends Widget {
      9     static $db = array(
     10         'ShowTitle' => 'Boolean',
     11         'Title' => 'Varchar(150)',
     12         'CanNotDelete' => 'Boolean',
     13         'Style' => 'Varchar',
     14     );
     15
     16     static $defaults = array(
     17         'ShowTitle' => 1,
     18     );
     19
     20     static $summary_fields = array('Title','WidgetType', 'EnabledTitle');
     21
     22     static $searchable_fields = array('Title', 'Enabled');
     23
     24     // максимальная ширина загружаемых картинок (то что больше - ресайзится)
     25     static $max_image_width = 4000;
     26
     27     // максимальная высота загружаемых картинок (то что больше - ресайзится)
     28     static $max_image_heigth = 4000;
     29
     30     // стили виджетов
     31     //static $styles = array(); - не используется из-за хитрого задания стилей (через Object::add_static_var)
     32
     33     /**
     34      * Задаем стили для виджетов
     35      *
     36      * @param string $class - класс виджета
     37      * @param array $styles - набор стилей
     38      */
     39     static function set_styles($class, $styles) {
     40         if (!is_array($styles)) $styles = array($styles);
     41         Object::add_static_var($class, 'styles', $styles);
     42     }
     43
     44     static function get_styles($class) {
     45         return Object::uninherited_static($class, 'styles');
     46     }
     47
     48     // список классов скрытых виджетов,
     49     private static $hidden_widgets = array();
     50
     51     /**
     52      * Добавить скрытый виджет
     53      *
     54      * @param string $class - класс виджета
     55      */
     56     static function hide_widget($class) {
     57         self::$hidden_widgets[$class] = $class;
     58     }
     59
     60     /**
     61      * Установить список скрытых виджетов
     62      *
     63      * @param array $classes - массив классов виджета
     64      */
     65     static function set_hidden_widgets($classes) {
     66         self::$hidden_widgets = array();
     67         foreach ($classes as $class) {
     68             self::hide_widget($class);
     69         }
     70     }
     71
     72     /**
     73      * Является ли виджет скрытым
     74      *
     75      * @param string $widget - класс виджета
     76      *
     77      * @return bool
     78      */
     79     static function is_hidden_widget($class) {
     80         return array_key_exists($class, self::$hidden_widgets);
     81     }
     82
     83     /**
     84      * Возврат локализованных значений массива по классу и полю
     85      *
     86      * @param string $class - класс объекта
     87      * @param string $field - поле объекта
     88      * @param array $options - набор значений поля объекта
     89      *
     90      * @return array - набор локализованных значений поля объекта
     91      */
     92     static function get_array_localization($class, $field, $options) {
     93         $rs = array();
     94         if ($options) {
     95             foreach ($options as $val) {
     96                 $rs[$val] = _t("{$class}.{$field}_{$val}", $val);
     97             }
     98         }
     99         return $rs;
    100     }
    101
    102     /*
    103      * Проверка возможности создания виджета
    104      * Если у виджета объявлена переменная класса needObjects и она содержит массив, то по ней проверяется наличие необходимых классов и созданных страниц
    105      * Если индекс элемента массива равен Page - то проверям на наличие страницы класса, заданного в значении элемента массива; иначе только на наличие такого класса
    106      * Дополнительно проверям на скрытость виджета
    107      */
    108     function canCreate($area = null) {
    109         if (self::is_hidden_widget($this->class))
    110             return false;
    111         if ($area) {
    112             if (is_a($area, 'WebylonWidgetArea') && !is_a($this, $area::$widgetClass))
    113                 return false;
    114
    115             $allowed = SiteConfigWidgets::get_allowed_area_widgets($area);
    116             if ($allowed) {
    117                 if (is_array($allowed) && (array_search($this->ClassName, $allowed) === false)) {
    118                     return false;
    119                 } elseif (is_string($allowed) && ($this->ClassName != $allowed)) {
    120                     return false;
    121                 }
    122             }
    123         }
    124         if (isset($this->needObjects) && is_array($this->needObjects) && count($this->needObjects)) {
    125             foreach ($this->needObjects as $class => $type) {
    126                 if (class_exists($class) && !self::is_hidden_widget($this->class)) {
    127                     if ($type == 'Page') {
    128                         return DataObject::get_one($class);
    129                     }
    130                     return true;
    131                 }
    132             }
    133             return false;
    134         }
    135         return true;
    136     }
    137
    138     function canDelete() {
    139         return !$this->CanNotDelete;
    140     }
    141
    142     function onBeforeWrite() {
    143         parent::onBeforeWrite();
    144         if (!$this->ID) {
    145             if ($peers = DataObject::get('WebylonWidget')) {
    146                 $this->Sort = $peers->Count()+1;
    147             }
    148         }
    149     }
    150
    151     function onBeforeDelete() {
    152         parent::onBeforeDelete();
    153
    154         if ($this->hasValue('Items') && $this->Items() && $this->Items()->Count()) {
    155             foreach($this->Items() as $item) {
    156                 $item->delete();
    157             }
    158         }
    159     }
    160
    161     function fieldLabels($relations = true) {
    162         $fields = parent::fieldLabels($relations);
    163         $fields['EnabledTitle'] = $fields['Enabled'];
    164
    165         return $fields;
    166     }
    167
    168     function getCMSFields() {
    169         $fields = parent::getCMSFields();
    170         $styles = self::get_styles($this->class);
    171         if (count($styles) == 0) {
    172             $fields->removeByName('Style');
    173         } elseif (count($styles) == 1) {
    174             $fields->replaceField('Style', new HiddenField('Style', '', $styles[0]));
    175         } else {
    176             $fields->replaceField('Style', new DropdownField('Style', $this->fieldLabel('Style'), WebylonWidget::get_array_localization($this->class, 'Style', $styles)));
    177         }
    178         if (Director::isDev()) {
    179             $tab = $fields->findOrMakeTab('Root.Main');
    180             $tab->insertBefore(new CheckboxField('CanNotDelete', $this->fieldLabel('CanNotDelete')), 'Enabled');
    181         }
    182         else {
    183             $fields->removeByName('CanNotDelete');
    184         }
    185         return $fields;
    186     }
    187
    188     // сообщение на случай отсутствия класса, используемого в виджете (напр. SpecialCatalog)
    189     function getFailCMSFields() {
    190         $fields = new FieldSet();
    191         $fields->push(new HiddenField('ParentID'));
    192         if (isset($this->needObjects) && is_array($this->needObjects)) {
    193             foreach($this->needObjects as $class=>$type) {
    194                 $fields->push(new LiteralField("Create{$class}", sprintf(_t('WebylonWidget.CreateObject'), $class)));
    195             }
    196         }
    197         return $fields;
    198     }
    199
    200     function getCMSActions() {
    201         $fields = new FieldSet();
    202         if ($this->canDelete()) {
    203             $fields->push(new FormAction('doDeleteWidget', 'Удалить виджет'));
    204         }
    205         $fields->push(new FormAction('save', 'Сохранить виджет'));
    206         return $fields;
    207     }
    208
    209     function populateDefaults(){
    210         parent::populateDefaults();
    211         if (!$this->Title) {
    212             $this->Title = $this->WidgetType();
    213         }
    214         // ??? под вопросом - нужно ли ???
    215         $styles = self::get_styles($this->class);
    216         if (count($styles)) {
    217             $this->Style = $styles[0];
    218         }
    219     }
    220
    221     function getActive() {
    222         return $this->Enabled;
    223     }
    224
    225     function CMSTitle() {
    226         return $this->Title();
    227     }
    228
    229     function Title() {
    230         return ($this->Title) ? $this->Title : $this->i18n_singular_name();
    231     }
    232
    233     function WidgetType() {
    234         return $this->i18n_singular_name();
    235     }
    236
    237     function WidgetHolder() {
    238         return $this->forTemplate();
    239     }
    240
    241     function forTemplate() {
    242         return $this->renderWith($this->getTemplates());
    243     }
    244
    245     function getTemplates() {
    246         $templates = array();
    247         $class = $this->ClassName;
    248
    249         while ($class) {
    250             if ($this->hasValue('Style'))
    251                 $templates[] = $class . '_' . $this->Style;
    252             $templates[] = $class;
    253             $class = get_parent_class($class);
    254         }
    255         return $templates;
    256     }
    257
    258     /**
    259      * Проверка наличия в виджете содержания
    260      * - если есть активные элементы для итерации
    261      * - если есть существующий holder (в большинстве виджетов требуется доп.проверка на наличие элементов в holder)
    262      * - есть Text
    263      *
    264      * @return <type>
    265      */
    266     function hasContent() {
    267         if ($this->hasMethod('Items') && $this->Items('Active = 1')->Count()) {
    268             return true;
    269         }
    270         if ($this->hasMethod('Holder') && $this->HolderID && ($holder = $this->Holder()) && $holder->ID) {
    271             return true;
    272         }
    273         if ($this->hasValue('Text')) {
    274             return true;
    275         }
    276         return false;
    277     }
    278
    279     /**
    280      * Ссылка на раздел сайта, свзяанный с виджетом
    281      *
    282      *
    283      * @return (string) Link
    284      */
    285     function getMoreLink() {
    286         return false;
    287     }
    288
    289     function CurrentPage() {
    290         return Director::get_current_page();
    291     }
    292 }
    293
    294 class WebylonWidget_Item extends DataObject {
    295     static $db = array(
    296         'Active' => 'Boolean',
    297         'Title' => 'Varchar(200)',
    298         'LinkType' => "Enum('none, internal, external')",
    299         'ExternalLink' => 'Varchar(255)',
    300         'NewWindow' => 'Boolean',
    301         'Style' => 'Varchar',
    302     );
    303
    304     static $defaults = array(
    305         'LinkType' => 'none',
    306         'Active' => 1,
    307     );
    308
    309     static $has_one = array(
    310         'Widget' => 'WebylonWidget',
    311         'InternalLink' => 'SiteTree'
    312     );
    313
    314     static $summary_fields = array('Title', 'Link', 'ActiveTitle');
    315
    316     static $searchable_fields = array('Title', 'Title');
    317
    318     /**
    319      * Задаем стили для списочных элементов виджета
    320      *
    321      * @param string $class - класс виджета
    322      * @param array $styles - набор стилей
    323      */
    324     static function set_styles($class, $styles) {
    325         if (!is_array($styles)) $styles = array($styles);
    326         Object::add_static_var($class, 'styles', $styles);
    327     }
    328
    329     static function get_styles($class) {
    330         return Object::combined_static($class, 'styles');
    331     }
    332
    333     function fieldLabels($includerelations = true) {
    334         $fields = parent::fieldLabels($includerelations);
    335         $fields['Link'] = _t('WebylonWidget_Item.Link', 'Link');
    336         $fields['ActiveTitle'] = $fields['Active'];
    337         return $fields;
    338     }
    339
    340     function getCMSFields() {
    341         $fields = parent::getCMSFields();
    342         $fields->removeByName('SortOrder');
    343         $fields->removeByName('ExternalLink');
    344         $fields->removeByName('InternalLinkID');
    345
    346         $styles = self::get_styles($this->class);
    347         if (count($styles) == 0) {
    348             $fields->removeByName('Style');
    349         } elseif (count($styles) == 1) {
    350             $fields->replaceField('Style', new HiddenField('Style', '', $styles[0]));
    351         } else {
    352             $fields->replaceField('Style', new DropdownField('Style', $this->fieldLabel('Style'), WebylonWidget::get_array_localization($this->class, 'Style', $styles)));
    353         }
    354
    355         $fields->addFieldToTab('Root.Main', new SelectionGroup('LinkType', array(
    356             'none//' . _t('WebylonWidget_Item.db_LinkType_none', 'No Link') => new LiteralField('NoLink', ''),
    357             'internal//' . _t('WebylonWidget_Item.db_LinkType_internal', $this->fieldLabel('InternalLink')) => new TreeDropdownField('InternalLinkID', '', 'SiteTree'),
    358             'external//' . _t('WebylonWidget_Item.db_LinkType_external', $this->fieldLabel('ExternalLink')) => new TextField('ExternalLink', ''),
    359         )));
    360         $fields->addFieldToTab('Root.Main', new LabelField('LinkTypeName', $this->fieldLabel('LinkType')), 'LinkType');
    361         $fields->addFieldToTab('Root.Main', $fields->dataFieldByName('NewWindow'));
    362
    363         return $fields;
    364     }
    365
    366     public function Link() {
    367         $link = '';
    368         switch ($this->LinkType) {
    369             case 'external':
    370                 $link = $this->ExternalLink;
    371                 break;
    372             case 'internal':
    373                 if ($this->InternalLink()) {
    374                     $link = $this->InternalLink()->Link();
    375                 }
    376                 break;
    377             default:
    378                 break;
    379         }
    380         return $link;
    381     }
    382
    383     function ActiveTitle() {
    384         return ($this->Active) ? _t('Boolean.YES','YES') : _t('Boolean.NO','NO');
    385     }
    386
    387     // является ли данный элемент меню текущим - ссылка с него ведет на текущую страницу
    388     function IsCurrent() {
    389         if ($this->LinkType == 'none') {
    390             return false;
    391         }
    392         $controller = Controller::curr();
    393         $link = $this->Link();
    394         if ($link == '/') {
    395             $link = '/home/';
    396         }
    397         $currentLink = $controller->Link();
    398         if ($link == $currentLink) {
    399             return true;
    400         }
    401         return false;
    402     }
    403
    404     function LinkOrCurrent() {
    405         if ($this->IsCurrent()) {
    406             return 'current';
    407         }
    408         return 'link';
    409     }
    410
    411     function IsLink() {
    412         if (!$this->IsCurrent()) {
    413             return true;
    414         }
    415         return false;
    416     }
    417 }
    418

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