Source of file News.php
Size: 17,783 Bytes - Last Modified: 2021-12-24T06:47:36+00:00
/var/www/docs.ssmods.com/process/src/code/objects/News.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557 | <?php /** * The news. * Sit back and relax, this might take a while. * History is NOT supported. Only the URLSegment is being tracked. This makes it a bit more simplistic. * * @package News/blog module * @author Simon 'Sphere' * * StartGeneratedWithDataObjectAnnotator * @property string Title * @property string Author * @property string URLSegment * @property string Synopsis * @property string Content * @property string PublishFrom * @property boolean Tweeted * @property boolean FBPosted * @property boolean Live * @property boolean Commenting * @property string Type * @property string External * @property string FAIcon * @property int ImpressionID * @property int DownloadID * @property int AuthorHelperID * @method Image Impression * @method File Download * @method AuthorHelper AuthorHelper * @method DataList|Comment[] Comments * @method DataList|Renamed[] Renamed * @method DataList|SlideshowImage[] SlideshowImages * @method ManyManyList|Tag[] Tags * @method ManyManyList|NewsHolderPage[] NewsHolderPages * @mixin GoogleSitemapExtension * @mixin NewsSystemExtension * @mixin NewsCMSExtension * EndGeneratedWithDataObjectAnnotator */ class News extends DataObject implements PermissionProvider { private static $db = array( 'Title' => 'Varchar(255)', /** Author might be handled via Member, but that's not useful if you want a non-member to post in his/her name */ 'Author' => 'Varchar(255)', 'URLSegment' => 'Varchar(255)', 'Synopsis' => 'Text', 'Content' => 'HTMLText', 'PublishFrom' => 'Date', 'Tweeted' => 'Boolean(false)', 'FBPosted' => 'Boolean(false)', 'Live' => 'Boolean(true)', 'Commenting' => 'Boolean(true)', /** This is for the external location of a link */ 'Type' => 'Enum("news,external,download","news")', 'External' => 'Varchar(255)', ); private static $has_one = array( 'Impression' => 'Image', /** If you want to have a download-file */ 'Download' => 'File', /** Generic helper to have Author-specific pages */ 'AuthorHelper' => 'AuthorHelper', ); private static $has_many = array( 'Comments' => 'Comment', 'Renamed' => 'Renamed', 'SlideshowImages' => 'SlideshowImage', ); private static $many_many = array( 'Tags' => 'Tag', ); private static $belongs_many_many = array( 'NewsHolderPages' => 'NewsHolderPage', ); private static $summary_fields = array(); private static $searchable_fields = array(); private static $default_sort = 'PublishFrom DESC'; /** * Set defaults. Commenting (show comments if allowed in siteconfig) is default to true. * * @var array $defaults . Commenting is true, SiteConfig overrides this! */ private static $defaults = array( 'Commenting' => true, ); /** * On large databases, this is a small performance improvement. * * @var array $indexes . */ private static $indexes = array( 'URLSegment' => true, ); /** * Define singular name translatable * * @return string Singular name */ public function singular_name() { if (_t('News.SINGULARNAME')) { return _t('News.SINGULARNAME'); } else { return parent::singular_name(); } } /** * Define plural name translatable * * @return string Plural name */ public function plural_name() { if (_t('News.PLURALNAME')) { return _t('News.PLURALNAME'); } else { return parent::plural_name(); } } /** * Define sumaryfields; * * @return array $summaryFields */ public function summaryFields() { $summaryFields = parent::summaryFields(); $summaryFields = array_merge( $summaryFields, array( 'Title' => _t('News.TITLE', 'Title'), 'Author' => _t('News.AUTHOR', 'Author'), 'PublishFrom' => _t('News.PUBLISH', 'Publish from'), 'Status' => _t('News.STATUS', 'Status'), ) ); return $summaryFields; } /** * Define translatable searchable fields * * @return array $searchableFields translatable */ public function searchableFields() { $searchableFields = parent::searchableFields(); unset($searchableFields['PublishFrom']); $searchableFields['Title'] = array( 'field' => 'TextField', 'filter' => 'PartialMatchFilter', 'title' => _t('News.TITLE', 'Title') ); $searchableFields['Author'] = array( 'field' => 'TextField', 'filter' => 'PartialMatchFilter', 'title' => _t('News.AUTHOR', 'Author') ); return $searchableFields; } /** * Setup the fieldlabels and their translation. * * @param Boolean $includerelations * * @return array $labels an array of the FieldLabels */ public function fieldLabels($includerelations = true) { $labels = parent::fieldLabels($includerelations); $newsLabels = array( 'Title' => _t('News.TITLE', 'Title'), 'Author' => _t('News.AUTHOR', 'Author'), 'Synopsis' => _t('News.SUMMARY', 'Summary/Abstract'), 'Content' => _t('News.CONTENT', 'Content'), 'PublishFrom' => _t('News.PUBDATE', 'Publish from'), 'Live' => _t('News.PUSHLIVE', 'Published'), 'Commenting' => _t('News.COMMENTING', 'Allow comments on this item'), 'Type' => _t('News.NEWSTYPE', 'Type of item'), 'External' => _t('News.EXTERNAL', 'External link'), 'Download' => _t('News.DOWNLOAD', 'Downloadable file'), 'Impression' => _t('News.IMPRESSION', 'Impression image'), 'Comments' => _t('News.COMMENTS', 'Comments'), 'SlideshowImages' => _t('News.SLIDE', 'Slideshow'), 'Tags' => _t('News.TAGS', 'Tags'), 'NewsHolderPages' => _t('News.LINKEDPAGES', 'Linked pages'), 'Help' => _t('News.BASEHELPLABEL', 'Help') ); return array_merge($newsLabels, $labels); } /** * Free guess on what this button does. * * @todo make this work on multilanguage sites. * * @param string $action * * @return string Link to this object. */ public function Link($action = 'show/') { if ($config = SiteConfig::current_site_config()->ShowAction) { $action = $config . '/'; } /** @var NewsHolderPage $Page */ if ($Page = $this->NewsHolderPages()->first()) { return $Page->Link($action . $this->URLSegment); } return false; } /** * @inheritdoc */ public function getCMSFields() { $fields = parent::getCMSFields(); $this->extend('generateCMSFields', $fields); $this->extend('updateCMSFields', $fields); return $fields; } /** * This is quite handy, for meta-tags and such. * * @param string $action * * @return string Link. To the item. (Yeah, I'm super cereal here) */ public function AbsoluteLink($action = 'show/') { return Director::absoluteURL($this->Link($action)); } /** * Check if commenting on this item is allowed * * @return bool */ public function AllowComments() { return (SiteConfig::current_site_config()->Comments && $this->Commenting); } /** * The holder-page ID should be set if translatable, otherwise, we just select the first available one. * The NewsHolderPage should NEVER be doubled. */ public function onBeforeWrite() { parent::onBeforeWrite(); /** Check if we have translatable and a NewsHolderPage. If no HolderPage available, skip (Create an orphan) */ if (!$this->NewsHolderPages()->count()) { if (!class_exists('Translatable') && $page = NewsHolderPage::get()->first()) { $this->NewsHolderPages()->add($page); } elseif (class_exists('Translatable')) { Translatable::disable_locale_filter(); $page = NewsHolderPage::get()->first(); $this->NewsHolderPages()->add($page); Translatable::enable_locale_filter(); } } if (!$this->Type || $this->Type === '') { $this->Type = 'news'; } /** Set PublishFrom to today to prevent errors with sorting. New since 2.0, backward compatible. */ if (!$this->PublishFrom) { $this->PublishFrom = SS_Datetime::now()->Rfc2822(); } /** * Make sure the link is valid. */ if (substr($this->External, 0, 4) !== 'http' && $this->External != '') { $this->External = 'http://' . $this->External; } $this->setURLValue(); $this->setAuthorData(); } /** * {@inheritdoc} */ public function onAfterWrite() { parent::onAfterWrite(); $siteConfig = SiteConfig::current_site_config(); /** * This is related to another module of mine. * Check it at my repos: Silverstripe-Social. * It auto-tweets your new Newsitem. If the TwitterController exists ofcourse. * It doesn't auto-tweet if the publish-date is in the future. Also, it won't tweet when it's that date! * * @todo refactor this to a facebook/twitter oAuth method that a dev spent more time on developing than I did on my Social-module. */ if (class_exists('TwitterController')) { $date = SS_DateTime::now()->Format('Y-m-d'); if ($this->Live && $this->PublishDate <= $date && !$this->Tweeted && $siteConfig->TweetOnPost) { $this->Tweeted = true; $this->write(); } } } /** * Setup the URLSegment for this item and create a Renamed Object if it's a rename-action. */ private function setURLValue() { if (!$this->URLSegment || ($this->isChanged('Title') && !$this->isChanged('URLSegment'))) { if ($this->ID > 0) { $Renamed = new Renamed(); $Renamed->OldLink = $this->URLSegment; $Renamed->NewsID = $this->ID; $Renamed->write(); $this->URLSegment = singleton('SiteTree')->generateURLSegment($this->Title); if (strpos($this->URLSegment, 'page-') === false) { $URLSegment = $this->URLSegment; if ($this->LookForExistingURLSegment($URLSegment)) { $URLSegment = $this->URLSegment . '-' . $this->ID; } $this->URLSegment = $URLSegment; } } } } /** * test whether the URLSegment exists already on another Newsitem * * @param string $URLSegment chosen URLSegment * * @return boolean URLSegment already exists yes or no. */ private function LookForExistingURLSegment($URLSegment) { return (News::get() ->filter(array('URLSegment' => $URLSegment)) ->exclude(array('ID' => $this->ID)) ->count() !== 0); } /** * Setup the LinkingMode for menu-items. * * @return string */ public function LinkingMode() { /** @var Page_Controller $controller */ $controller = Controller::curr(); $params = $controller->getURLParams(); return $params['ID'] === $this->URLSegment ? 'current' : 'link'; } /** * Create the author if non-existing yet, and set his/her ID to this item. */ private function setAuthorData() { $this->Author = trim($this->Author); $nameParts = explode(' ', $this->Author); foreach ($nameParts as $key => $namePart) { if ($namePart === '') { unset($nameParts[$key]); } } $this->Author = implode(' ', $nameParts); /** @var AuthorHelper $author */ $author = AuthorHelper::get()->filter('OriginalName', trim($this->Author)); if (!$author->Count()) { $author = AuthorHelper::create(); $author->OriginalName = trim($this->Author); $author->write(); } else { $author = $author->first(); } $this->AuthorHelperID = $author->ID; } /** * Get the allowed comments * * @return DataList with comments */ public function getAllowedComments() { return $this->Comments() ->filter(array('AkismetMarked' => false, 'Visible' => true)); } /** * Get the year this object is created. * * @return Int $yearItems String of 4 numbers representing the year */ public function getYearCreated() { return $this->dbObject('PublishFrom')->Format('Y'); } /** * Get the month this object is published * * @return string $monthItems double-digit representation of the month this object was published. */ public function getMonthCreated() { return $this->dbObject('PublishFrom')->Format('F'); } /** * Create a date-string based on the locale. Looks better. * * @return string * @todo this needs some work and improvement */ public function getPublished() { // i18n::get_date_format(); // $locale = i18n::get_locale(); // $date = new Zend_Date(); // $date->set($this->PublishFrom, null, $locale); // return substr($date->getDate($locale), 0, -9); } /** * Permissions */ public function providePermissions() { return array( 'CREATE_NEWS' => array( 'name' => _t('News.PERMISSION_CREATE_DESCRIPTION', 'Create newsitems'), 'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'), 'help' => _t('News.PERMISSION_CREATE_HELP', 'Permission required to create new newsitems.') ), 'EDIT_NEWS' => array( 'name' => _t('News.PERMISSION_EDIT_DESCRIPTION', 'Edit newsitems'), 'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'), 'help' => _t('News.PERMISSION_EDIT_HELP', 'Permission required to edit existing newsitems.') ), 'DELETE_NEWS' => array( 'name' => _t('News.PERMISSION_DELETE_DESCRIPTION', 'Delete newsitems'), 'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'), 'help' => _t('News.PERMISSION_DELETE_HELP', 'Permission required to delete existing newsitems.') ), 'VIEW_NEWS' => array( 'name' => _t('News.PERMISSION_VIEW_DESCRIPTION', 'View newsitems'), 'category' => _t('Permissions.CONTENT_CATEGORY', 'Content permissions'), 'help' => _t('News.PERMISSION_VIEW_HELP', 'Permission required to view existing newsitems.') ), ); } /** * {@inheritdoc} */ public function canCreate($member = null) { return Permission::checkMember($member, array('CREATE_NEWS', 'CMS_ACCESS_NewsAdmin')); } /** * {@inheritdoc} */ public function canEdit($member = null) { return Permission::checkMember($member, array('EDIT_NEWS', 'CMS_ACCESS_NewsAdmin')); } /** * {@inheritdoc} */ public function canDelete($member = null) { return Permission::checkMember($member, array('DELETE_NEWS', 'CMS_ACCESS_NewsAdmin')); } /** * {@inheritdoc} */ public function canView($member = null) { return (Permission::checkMember($member, array('VIEW_NEWS', 'CMS_ACCESS_NewsAdmin')) || $this->Live === 1); } /** * Helper function to determine if this News object is already published or not * * @return bool */ public function isPublished() { return $this->Live; } /** * Returns if the news item is published or not * * @return string */ public function getStatus() { $published = $this->isPublished() ? _t('News.IsPublished', 'published') : _t('News.IsUnpublished', 'not published'); if ($this->isPublished() && $this->PublishFrom > SS_Datetime::now()->Rfc2822()) { $published = _t('News.InQueue', 'Awaiting publishdate'); } return $published; } /** * Publishes a news item * * @throws ValidationException */ public function doPublish() { if (!$this->canEdit()) { throw new ValidationException(_t('News.PublishPermissionFailure', 'No permission to publish or unpublish news item')); } $this->Live = true; $this->write(); } /** * Unpublishes an news item * * @throws ValidationException */ public function doUnpublish() { if (!$this->canEdit()) { throw new ValidationException(_t('News.PublishPermissionFailure', 'No permission to publish or unpublish news item')); } $this->Live = false; $this->write(); } } |