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 29 30 31 32 33 34 35
36 static $hidden_cms_fields = array();
37
38 39 40 41 42 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 50 51
52 function hiddenCMSFields() {
53 $fieldsToHide = array();
54 $class = get_called_class();
55
56
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 86 87 88
89 function hide_cms_fields(& $fields) {
90 foreach($this->hiddenCMSFields() as $field) {
91
92
93 $fields->removeByName($field);
94 }
95 }
96
97 98 99 100 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
116 if (!class_exists('CommentsSiteConfig')) {
117 $fields->removeByName('ProvideComments');
118 } else {
119 if (!$this->allowComments()) {
120 $fields->removeByName('ProvideComments');
121 }
122 }
123
124
125 $fields->push(new HiddenField('ShowOnlyInTab', 'ShowOnlyInTab'));
126
127
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
148
149
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
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
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 ($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
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
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
409
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
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
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.
-