Version: current

      1 <?php
      2
      3 class Page extends SiteTree {
      4
      5     static $db = array(
      6         'AutoChild' => 'Boolean',
      7         'ShowOnlyInTab' => 'Boolean',
      8         'DevEditType' => "Enum('Open, Fixed, Close')",
      9         'ShowInSiteMap' => "Boolean",
     10     );
     11     static $defaults = array(
     12         'AutoChild' => 1,
     13         'ShowOnlyInTab' => 0,
     14         'ProvideComments' => 0,
     15         "DevEditType" => "Open",
     16         'ShowInSiteMap' => 1,
     17     );
     18     static $summary_fields = array(
     19         'PageTitle' => 'Title'
     20     );
     21
     22     static $default_child = 'DocPage';
     23
     24     /**
     25      * скрытие ненужных полей из админки
     26      *
     27      * пример:
     28      * static $hidden_cms_fields = array(
     29      *  '*' => array('Field1', 'Field2'),       // скрыть у всех страниц класса Field1 и Field2
     30      *  'ParentID' => array(                    // условное скрытие по значению поля ParentID
     31      *      1234 => array('Field3', 'Field4'),  // если поле ParentID == 1234 - скрываем Field3 и Field4
     32      *      2345 => 'Field5',                   // если поле ParentID == 2345 - скрываем Field5
     33      *  ),
     34      * )
     35      */
     36     static $hidden_cms_fields = array();
     37
     38     /**
     39      * Задает значение $hidden_cms_fields
     40      * Для исопльзование в конфиге
     41      *
     42      * @param array $fields
     43      */
     44     static function set_hidden_cms_fields($fields) {
     45         SS_Object::set_static(get_called_class(), 'hidden_cms_fields', $fields);
     46     }
     47
     48     /**
     49      * Определяет какие поля надо скрыть у текущей страницы по описанию из $hidden_cms_fields
     50      *
     51      */
     52     function hiddenCMSFields() {
     53         $fieldsToHide = array();
     54         $class = get_called_class();
     55         // get_static() - без наследования
     56         // combined_static() - с наследованием
     57         if (($hidden_cms_fields = SS_Object::combined_static($class, 'hidden_cms_fields')) && is_array($hidden_cms_fields)) {
     58             foreach($hidden_cms_fields as $name => $specOrName) {
     59                 if ($name == '*') {
     60                     if (is_array($specOrName)) {
     61                         $fieldsToHide = array_merge($fieldsToHide, $specOrName);
     62                     }
     63                     else {
     64                         $fieldsToHide[] = $specOrName;
     65                     }
     66                 }
     67                 elseif (is_array($specOrName)) {
     68                     foreach($specOrName as $val => $fieldList) {
     69                         if ($this->{$name} == $val) {
     70                             if (is_array($fieldList)) {
     71                                 $fieldsToHide = array_merge($fieldsToHide, $fieldList);
     72                             }
     73                             else {
     74                                 $fieldsToHide[] = $fieldList;
     75                             }
     76                         }
     77                     }
     78                 }
     79             }
     80         }
     81         return $fieldsToHide;
     82     }
     83
     84     /**
     85      * Скрывает поля из формы в CMS по описанию из $hidden_cms_fields
     86      *
     87      * @param FieldSet $fields
     88      */
     89     function hide_cms_fields(& $fields) {
     90         foreach($this->hiddenCMSFields() as $field) {
     91             // только поля с данными, без вкладок
     92             // TODO как удалять вкладки?
     93             $fields->removeByName($field);
     94         }
     95     }
     96
     97     /**
     98      * Проверка возможность публикации из cli
     99      * @param Member $member
    100      * @return Boolean
    101      */
    102     public function canPublish($member = null) {
    103         if (Director::is_cli())
    104             return true;
    105         return parent::canPublish($member);
    106     }
    107
    108     function getCMSFields() {
    109         HtmlEditorConfig::set_active('cms');
    110         $fields = parent::getCMSFields();
    111
    112         if ($this->stat('allowed_children') != 'none')
    113             $fields->addFieldToTab('Root.Behaviour', new CheckboxField("AutoChild", _t('Page.AUTOCHILD', "Автоматически открывать поддокумент если нет своего содержания")), 'ProvideComments');
    114
    115         /* comments */
    116         if (!class_exists('CommentsSiteConfig')) {
    117             $fields->removeByName('ProvideComments');
    118         } else {
    119             if (!$this->allowComments()) {
    120                 $fields->removeByName('ProvideComments');
    121             }
    122         }
    123         /* end_comments */
    124
    125         $fields->push(new HiddenField('ShowOnlyInTab', 'ShowOnlyInTab'));
    126
    127         /* subsites */
    128         if (singleton('SiteTree')->hasExtension('SiteTreeSubsites')) {
    129             $fields->removeByName('BaseUrlLabel');
    130             $primaryDomain = $this->Subsite()->getPrimaryDomain() . '/';
    131             if ($primaryDomain[0] == '/') {
    132                 $primaryDomain = substr(Director::absoluteBaseURL(), 0, -1) . $primaryDomain;
    133             } else {
    134                 $primaryDomain = 'http://' . $primaryDomain;
    135             }
    136             $fields->addFieldToTab('Root.Content.Metadata',
    137                     new LabelField(
    138                             'BaseUrlLabel',
    139                             Controller::join_links(
    140                                     $primaryDomain,
    141                                     (self::nested_urls() && $this->ParentID ? $this->Parent()->RelativeLink(true) : null)
    142                             )
    143                     ),
    144                     'URLSegment'
    145             );
    146         }
    147         /* end_subsites */
    148
    149         /* permissons for page */
    150         if (Director::isDev()) { // Если в в режиме разаработки
    151             $editOptions = new OptionsetField('DevEditType', "");
    152             $editOptionsSource = array();
    153             $editOptionsSource["Open"] = _t('PageDevOptions.OPEN', "Open for all");
    154             $editOptionsSource["Fixed"] = _t('PageDevOptions.FIXED', "Fixed Page");
    155             $editOptionsSource["Close"] = _t('PageDevOptions.CLOSE', "Close for all");
    156             $editOptions->setSource($editOptionsSource);
    157
    158             $fields->addFieldToTab('Root.Access', new HeaderField('WhoCanDevEditHeader', _t('SiteTree.EDITDEVHEADER', "Who can dev edit this page?"), 2));
    159             $fields->addFieldToTab('Root.Access', $editOptions);
    160         } else {
    161             $fields->removeByName('HomepageForDomain');
    162             $fields->removeByName('HomepageForDomainInfo');
    163             if ($this->DevEditType == 'Close') {
    164                 $fields->makeReadonly();
    165             }
    166             else {
    167                 $fields->replaceField('ClassName', new HiddenField('ClassName', '', $this->ClassName));
    168                 $fields->removeByName('NumberCMSChildren');
    169
    170                 if ($this->DevEditType == 'Fixed') {
    171                     $fields->removeByName('ParentType');
    172                     $fields->removeByName('ParentID');
    173
    174                     $fields->removeByName('BaseUrlLabel');
    175                     $fields->removeByName('TrailingSlashLabel');
    176                     $fields->removeByName('URL');
    177                     $fields->removeByName('URLSegment');
    178                 }
    179             }
    180         }
    181         // SiteMap
    182         if ($this->ShowOnlyInTab) {
    183             $fields->removeByName('ShowInMenus');
    184         }
    185         else {
    186             $fields->addFieldToTab('Root.Behaviour', new CheckboxField('ShowInSiteMap', _t('Page.ShowInSiteMap', 'Show In Sitemap')), 'ShowInSearch');
    187         }
    188
    189         Requirements::customScript("
    190             Behaviour.register({
    191                 '#Form_EditForm' : {
    192                     initialize : function() {
    193                         this.observeMethod('PageLoaded', this.MediawebPageHandler);
    194                         this.MediawebPageHandler();
    195                     },
    196                     MediawebPageHandler : function() {
    197                         (function($) {
    198
    199                             if (($('#Form_EditForm_folder_id').length) && ($('input#Form_EditForm_folder_id').attr('folder_updated') != '1')) {
    200                                 if ($('#TreeDropdownField_Form_EditorToolbarImageForm_FolderID')) {
    201                                     $('#TreeDropdownField_Form_EditorToolbarImageForm_FolderID')[0].setValue($('#Form_EditForm_folder_id').val());
    202                                     $('#TreeDropdownField_Form_EditorToolbarImageForm_FolderID')[0].refresh();
    203                                 }
    204                                 if ($('#TreeDropdownField_Form_EditorToolbarFlashForm_FolderID')) {
    205                                     $('#TreeDropdownField_Form_EditorToolbarFlashForm_FolderID')[0].setValue($('#Form_EditForm_folder_id').val());
    206                                     $('#TreeDropdownField_Form_EditorToolbarFlashForm_FolderID')[0].refresh();
    207                                 }
    208                                 if ($('#TreeDropdownField_Form_EditorToolbarLinkForm_file')) {
    209                                     $('#TreeDropdownField_Form_EditorToolbarLinkForm_file')[0].setValue($('#Form_EditForm_folder_path').val());
    210                                     $('#TreeDropdownField_Form_EditorToolbarLinkForm_file')[0].refresh();
    211                                 }
    212                                 $('input#Form_EditForm_folder_id').attr('folder_updated','1');
    213                             }
    214                         })(jQuery);
    215                     }
    216                 }
    217             });
    218         ");
    219         //if ($('#Form_EditForm_folder_id').val()) {
    220         return $fields;
    221     }
    222
    223     function checkDevPermisson($member=null, $method=null) {
    224         if (Director::isDev() && ($method != 'canDelete'))
    225             return true;
    226         if (!$member) {
    227             $member = Member::currentUser();
    228         }
    229         $permisson = $this->DevEditType;
    230         if ($method) {
    231             switch ($method) {
    232                 case 'canAddChildren':
    233                     if ($permisson == 'Close') {
    234                         return false;
    235                     }
    236                     break;
    237
    238                 case 'canDelete':
    239                     if ($permisson == 'Close' || $permisson == 'Fixed') {
    240                         return false;
    241                     }
    242                     break;
    243
    244                 case 'canDeleteFromLive':
    245                     if ($permisson == 'Close' || $permisson == 'Fixed') {
    246                         return false;
    247                     }
    248                     break;
    249
    250                 case 'canEdit':
    251                     if ($permisson == 'Close') {
    252                         return false;
    253                     }
    254                     break;
    255
    256                 case 'canReorder':
    257                     if ($permisson == 'Close' || $permisson == 'Fixed')
    258                         return false;
    259                     break;
    260
    261                 default:
    262                     break;
    263             }
    264         }
    265         return true;
    266     }
    267
    268     function canAddChildren($member = null) {
    269         $result = parent::canAddChildren($member);
    270         if (!$result)
    271             return false;
    272         return $this->checkDevPermisson($member, 'canAddChildren');
    273     }
    274
    275     function canDelete($member = null) {
    276         $result = parent::canDelete($member);
    277         if (!$result)
    278             return false;
    279         return $this->checkDevPermisson($member, 'canDelete');
    280     }
    281
    282     function canDeleteFromLive($member = null) {
    283         $result = parent::canDeleteFromLive($member);
    284         if (!$result)
    285             return false;
    286         return $this->checkDevPermisson($member, 'canDeleteFromLive');
    287     }
    288
    289     function canEdit($member = null) {
    290         $result = parent::canEdit($member);
    291         if (!$result)
    292             return false;
    293         return $this->checkDevPermisson($member, 'canEdit');
    294     }
    295
    296     function allowComments($siteconfig=false) {
    297         if (!class_exists('CommentsSiteConfig')) {
    298             return false;
    299         }
    300         $sc = SiteConfig::current_site_config();
    301         $action = $sc->CommentsDefaultAction;
    302         $classes = $sc->CommentsExeptClasses;
    303         $classes = explode(',', $classes);
    304         switch ($action) {
    305             case 'Allow':
    306                 if (in_array($this->class, $classes)) {
    307                     return false;
    308                 }
    309                 break;
    310             case 'Deny':
    311                 if (!in_array($this->class, $classes)) {
    312                     return false;
    313                 }
    314                 break;
    315             default:
    316                 break;
    317         }
    318
    319         return true;
    320     }
    321
    322     function DevMode() {
    323         return Director::isDev();
    324     }
    325
    326     private function childClass() {
    327         //Debug::show(DataObject::get('SiteTree', 'ParentID = '.$this->ID));
    328         return DataObject::get('SiteTree', 'ParentID = ' . $this->ID);
    329     }
    330
    331     function onBeforeWrite() {
    332         $defaults = singleton($this->ClassName);
    333         $defaults->populateDefaults();
    334         $this->ShowOnlyInTab = $defaults->ShowOnlyInTab;
    335         if ($this->ShowOnlyInTab) {
    336             $this->ShowInMenus = 0;
    337             $this->ShowInSiteMap = 0;
    338         }
    339
    340         if (!class_exists('CommentsSiteConfig')) {
    341             $this->ProvideComments = false;
    342         }
    343         parent::onBeforeWrite();
    344     }
    345
    346     function onAfterWrite() {
    347         parent::onAfterWrite();
    348
    349     }
    350
    351     function onAfterDelete() {
    352         parent::onAfterDelete();
    353
    354     }
    355
    356     public function Lang() {
    357         return i18n::get_lang_from_locale(i18n::get_locale());
    358     }
    359
    360     public function Locale() {
    361         return i18n::get_locale();
    362     }
    363
    364     function populateDefaults() {
    365         $this->ProvideComments = $this->allowComments();
    366         parent::populateDefaults();
    367     }
    368
    369     function MetaTags($includeTitle = true) {
    370         $sc = SiteConfig::current_site_config();
    371         $tags = "";
    372         $includeTitle = ($includeTitle === true || $includeTitle == 'true');
    373         if ($includeTitle) {
    374             $title = ($this->MetaTitle) ? $this->MetaTitle : $this->Title;
    375             if ($this->SeoPageNumber) $title .=  ' ' . _t('SEO.PageNumber', 'page ') . $this->SeoPageNumber;
    376             if ($sc->Title && !$this->MetaTitle)
    377                     $title .= ' - ' . $sc->Title;
    378             $tags .= "<title>" . Convert::raw2xml($title) . "</title>\n";
    379         }
    380
    381         $tags .= '<meta http-equiv="Content-type" content="text/html; charset=' . ContentNegotiator::get_encoding() . "\" />\n";
    382         $locale = (Controller::has_curr() && Controller::curr()->hasMethod('ContentLocale')) ? Controller::curr()->ContentLocale() : $this->Locale();
    383         $tags .= '<meta http-equiv="Content-Language" content="' . $locale ."\" />\n";
    384
    385         // Расширяем получение метатегов
    386         // favicon
    387         if ($sc->FavIconID && ($favicon = $sc->FavIcon()) && $favicon->ID) {
    388             $tags .= "<link rel=\"shortcut icon\" href=\"{$favicon->getURL()}\" />\n";
    389         }
    390
    391         if (!$this->MetaKeywords) {
    392             $this->MetaKeywords = $sc->MetaKeywords;
    393         }
    394
    395         if (!$this->MetaDescription) {
    396             $this->MetaDescription = $sc->MetaDescription;
    397         }
    398
    399         $this->ExtraMeta .= $sc->MetaTags;
    400
    401         if ($this->MetaKeywords) {
    402             $tags .= "<meta name=\"keywords\" content=\"" . Convert::raw2att($this->MetaKeywords) . "\" />\n";
    403         }
    404         if ($this->MetaDescription) {
    405             $tags .= "<meta name=\"description\" content=\"" . Convert::raw2att($this->MetaDescription) . "\" />\n";
    406         }
    407         if ($this->ExtraMeta) {
    408             // $tags .= $this->ExtraMeta . "\n";
    409             // RNW
    410             // Ищем допустимые тэги
    411             // все остальное просто пропускаем
    412             $pattern = array(
    413                 "<meta[\s\S]*?\/>" => "<%match% >\n",
    414                 '#<style>(.*?)</style>#is' => "%match%\n",
    415                 '#<script>(.*?)</script>#is' => "%match%\n",
    416                 '#<script(.*?)></script>#is' => "%match%\n",
    417
    418             );
    419             foreach ($pattern as $key => $value) {
    420                 $matches = array();
    421                 preg_match_all($key, $this->ExtraMeta, $matches);
    422                 foreach ($matches[0] as $match) {
    423                     $tags .= str_replace('%match%', $match, $value);
    424                 }
    425             }
    426         }
    427
    428         // SEO-теги
    429         if ($this->SeoIsAlternative) {
    430             $tags .= "<meta name=\"robots\" content=\"noindex\" />\n";
    431         }
    432         if ($this->SeoCanonicalLink) {
    433             $tags .= "<link rel=\"canonical\" href=\"{$this->SeoCanonicalLink}\" />\n";
    434         }
    435         if ($this->SeoNextLink) {
    436             $tags .= "<link rel=\"next\" href=\"{$this->SeoNextLink}\" />\n";
    437         }
    438         if ($this->SeoPrevLink) {
    439             $tags .= "<link rel=\"prev\" href=\"{$this->SeoPrevLink}\" />\n";
    440         }
    441
    442         $this->extend('MetaTags', $tags, $includeTitle);
    443
    444         return $tags;
    445     }
    446
    447     function AdminEmail() {
    448         return SiteConfig::current_site_config()->AdminEmail();
    449     }
    450
    451     function NestedValue($name = '') {
    452         if (!$name) return false;
    453         $p = $this;
    454         while ($p->ParentID > 0 && !$p->hasValue($name)) {
    455             $p = $p->Parent();
    456         }
    457         return $p->obj($name);
    458     }
    459
    460     function FinalParent($url = false) {
    461         $page = ($url) ? SiteTree::get_by_link($url) : $this;
    462         if (!$page) return false;
    463         while ($page->ParentID > 0) {
    464              $page = $page->Parent();
    465         }
    466         return $page;
    467     }
    468
    469 }
    470
    471 class Page_Controller extends ContentController {
    472
    473     private static $combined_files = array();
    474
    475     static function combine_files($name, $files, $theme = '*') {
    476         if (!$theme) $theme = '*';
    477         if (!is_array($files)) $files = preg_split('/ *, */', trim($files));
    478
    479         if ($theme != '*') $name = $theme . '_' . $name;
    480         self::$combined_files[$theme][$name] = $files;
    481     }
    482
    483     public function init() {
    484         parent::init();
    485         if ($this->AutoChild && $this->isEmptyContent() && (!isset($this->urlParams['Action']) || !$this->urlParams['Action'])) {
    486             $this->RedirectToFirstChild();
    487         }
    488
    489         SiteConfig::current_site_config()->setupAdminEmail();
    490
    491         $theme = SSViewer::current_theme();
    492         if ($theme) {
    493             $themeConfig = THEMES_PATH . DIRECTORY_SEPARATOR . $theme . DIRECTORY_SEPARATOR . '_config.php';
    494             if (file_exists($themeConfig))
    495                 include_once($themeConfig);
    496         }
    497         else $theme = '*';
    498
    499         if (isset(self::$combined_files[$theme])) {
    500             foreach (self::$combined_files[$theme] as $name => $files) {
    501                 if (count($files))
    502                     Requirements::combine_files($name, $files);
    503             }
    504         }
    505         $this->extend('onAfterInit');
    506     }
    507
    508     function isEmptyContent() {
    509         return (!$this->Content || $this->Content == '<p></p>');
    510     }
    511
    512     function RedirectToFirstChild() {
    513         $children = $this->Children();
    514         if ($firstChild = $children->First()) {
    515             return Director::redirect($firstChild->Link());
    516         }
    517         return false;
    518     }
    519
    520     function ShowWidget($id, $callerClass) {
    521         if (class_exists($callerClass))
    522             return singleton($callerClass)->Widget($id);
    523         return false;
    524     }
    525
    526     function SitePoll() {
    527         if (class_exists('ShowPoll')) {
    528             return new ShowPoll($this, 'SitePoll');
    529         }
    530         return false;
    531     }
    532
    533     function ImageGalleryRandomImage($AlbumID = null, $GalleryPageID = null) {
    534         // Проверим что модуль установлен
    535         if (singleton('SiteTree')->hasExtension('ImageGallerySiteTree')) {
    536             $Gallery = "";
    537             if (is_int($GalleryPageID)) {
    538                 $Gallery = "ID = $GalleryPageID";
    539             }
    540             $image_page = DataObject::get_one('ImageGalleryPage', $Gallery);
    541             if ($image_page) {
    542                 $image_item = $image_page->RandomImage($AlbumID);
    543                 return $image_item;
    544             }
    545         }
    546         return false;
    547     }
    548
    549     function Siblings() {
    550         return DataObject::get("Page", "ParentID = " . $this->ParentID);
    551     }
    552
    553     function HomePage() {
    554         return DataObject::get_one("HomePage");
    555     }
    556
    557     function BaseURL() {
    558         return Director::baseURL();
    559     }
    560
    561     function DocPath($maxDepth = 20, $unlinked = false, $stopAtPageType = false, $showHidden = false) {
    562         $page = $this;
    563         $parts = new DataObjectSet();
    564
    565         $i = 0;
    566         while ($page && (!$maxDepth || $i < $maxDepth) && (!$stopAtPageType || $page->ClassName != $stopAtPageType)) {
    567             if ($showHidden || $page->ShowInMenus || ($page->ID == $this->ID)) {
    568                 if ($page->URLSegment == 'home')
    569                     $hasHome = true;
    570                 $parts->insertFirst($page);
    571             }
    572             $page = $page->Parent;
    573             $i++;
    574         }
    575         return $parts;
    576     }
    577
    578     function Random($min = 0, $max = 100) {
    579         return rand($min, $max);
    580     }
    581
    582     function PageByID($id) {
    583         return DataObject::get_by_id('SiteTree', $id);
    584     }
    585     function PageByClass($class) {
    586         if (ClassInfo::exists($class)) {
    587             return DataObject::get_one($class, '', true, 'ID');
    588         }
    589         return false;
    590     }
    591
    592     function setSEOVars($dataobjectSet) {
    593         if (!$dataobjectSet) return;
    594         if ($dataobjectSet->Count() == 0) return;
    595         if ($dataobjectSet->MoreThanOnePage() && ($dataobjectSet->CurrentPage() > 1))
    596             $this->data()->SeoPageNumber = $dataobjectSet->CurrentPage();
    597         $this->data()->SeoNextLink = $dataobjectSet->NextLink();
    598         $this->data()->SeoPrevLink = $dataobjectSet->PrevLink();
    599     }
    600
    601     // получение FavIcon
    602     function FavIcon() {
    603         $sc = SiteConfig::current_site_config();
    604         if ($sc->FavIconID && $sc->FavIcon()) {
    605             return $sc->FavIcon();
    606         }
    607         return false;
    608     }
    609 }
    610
    611

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