From b077e587dfef87bd0d54a730a850324c313cf6b8 Mon Sep 17 00:00:00 2001 From: micmania1 Date: Sun, 4 Aug 2013 17:38:26 +0100 Subject: [PATCH] Added blog type dropdown to gridfield --- .gitignore | 4 + _config.php | 20 ++ _config/config.yml | 9 +- css/cms.css | 9 + extensions/BlogFilter.php | 65 ++++ extensions/BlogPostFilter.php | 61 +--- extensions/URLSegmentExtension.php | 48 +++ forms/AjaxTextField.php | 5 - forms/gridfield/GridFieldAddByDBField.php | 2 +- .../GridFieldConfig_AddByDBField.php | 15 - .../GridFieldSiteTreeAddNewButton.php | 93 +++++- javascript/GridField.js | 16 + model/BlogCategory.php | 27 +- model/BlogTag.php | 24 +- page/Blog.php | 286 ++++++++++++++---- page/BlogPost.php | 102 ++++++- templates/Includes/BlogPagination.ss | 21 ++ templates/Includes/BlogSideBar.ss | 3 + templates/Layout/Blog.ss | 18 -- templates/forms/BlogDropdownField_holder.ss | 3 + .../GridFieldAddByDBField.ss | 0 templates/forms/GridFieldSiteTreeAddNew.ss | 3 + .../forms/GridFieldSiteTreeAddNewButton.ss | 3 + templates/widgets/BlogArchiveWidget.ss | 9 + templates/widgets/BlogCategoriesWidget.ss | 7 + templates/widgets/BlogRecentPostsWidget.ss | 7 + templates/widgets/BlogTagsWidget.ss | 7 + widgets/BlogArchiveWidget.php | 81 +++++ widgets/BlogCategoriesWIdget.php | 35 +++ widgets/BlogRecentPostsWidget.php | 40 +++ widgets/BlogTagsWidget.php | 35 +++ 31 files changed, 879 insertions(+), 179 deletions(-) create mode 100644 .gitignore create mode 100755 css/cms.css create mode 100755 extensions/BlogFilter.php create mode 100755 extensions/URLSegmentExtension.php delete mode 100755 forms/AjaxTextField.php delete mode 100755 forms/gridfield/GridFieldConfig_AddByDBField.php create mode 100755 javascript/GridField.js create mode 100755 templates/Includes/BlogPagination.ss create mode 100755 templates/Includes/BlogSideBar.ss delete mode 100755 templates/Layout/Blog.ss create mode 100755 templates/forms/BlogDropdownField_holder.ss rename templates/{Includes => forms}/GridFieldAddByDBField.ss (100%) create mode 100755 templates/forms/GridFieldSiteTreeAddNew.ss create mode 100755 templates/forms/GridFieldSiteTreeAddNewButton.ss create mode 100755 templates/widgets/BlogArchiveWidget.ss create mode 100755 templates/widgets/BlogCategoriesWidget.ss create mode 100755 templates/widgets/BlogRecentPostsWidget.ss create mode 100755 templates/widgets/BlogTagsWidget.ss create mode 100755 widgets/BlogArchiveWidget.php create mode 100755 widgets/BlogCategoriesWIdget.php create mode 100755 widgets/BlogRecentPostsWidget.php create mode 100755 widgets/BlogTagsWidget.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3684b11 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.ssh/* +.bash* +.profile +vendor/* diff --git a/_config.php b/_config.php index 6fd199e..c311c41 100755 --- a/_config.php +++ b/_config.php @@ -1 +1,21 @@ + * + **/ +class BlogFilter extends Hierarchy { + + /** + * Augments (@link Hierarchy::stageChildren()} + * + * @param $staged DataList + * @param $showAll boolean + **/ + public function stageChildren($showAll = false) { + $staged = parent::stageChildren($showAll); + + $controller = Controller::curr(); + if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) { + return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames()); + } else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) { + + // Get the current stage. + $stage = Versioned::current_stage(); + if($stage == "Stage") $stage = ""; + else $stage = "_" . Convert::raw2sql($stage); + + $dataQuery = $staged->dataQuery() + ->innerJoin("BlogPost", "BlogPost" . $stage . ".ID = SiteTree" . $stage . ".ID") + ->where("PublishDate < NOW()"); + $staged = $staged->setDataQuery($dataQuery); + + } + return $staged; + } + + + + /** + * Augments (@link Hierarchy::liveChildren()} + * + * @param $staged DataList + * @param $showAll boolean + **/ + public function liveChildren($showAll = false, $onlyDeletedFromStage = false) { + $staged = parent::liveChildren($showAll, $onlyDeletedFromStage); + + $controller = Controller::curr(); + if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) { + return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames()); + } else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) { + $dataQuery = $staged->dataQuery() + ->innerJoin("BlogPost", "BlogPost_Live.ID = SiteTree_Live.ID") + ->where("PublishDate < NOW()"); + $staged = $staged->setDataQuery($dataQuery); + } + return $staged; + } + +} \ No newline at end of file diff --git a/extensions/BlogPostFilter.php b/extensions/BlogPostFilter.php index 6f7dac2..c3e6ea8 100755 --- a/extensions/BlogPostFilter.php +++ b/extensions/BlogPostFilter.php @@ -1,65 +1,18 @@ - * - **/ -class BlogPostFilter extends Hierarchy { +class BlogPostFilter extends DataExtension { /** - * Augments (@link Hierarchy::stageChildren()} - * - * @param $staged DataList - * @param $showAll boolean + * Augment queries so that we don't fetch unpublished articles. **/ - public function stageChildren($showAll = false) { - $staged = parent::stageChildren($showAll); + public function augmentSQL(SQLQuery &$query) { - $controller = Controller::curr(); - if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) { - return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames()); - } else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) { + $stage = Versioned::current_stage(); + if($stage == "Stage") $stage = ""; + else $stage = "_" . Convert::raw2sql($stage); - // Get the current stage. - $stage = Versioned::current_stage(); - if($stage == "Stage") $stage = ""; - else $stage = "_" . Convert::raw2sql($stage); + $query->addWhere("PublishDate < NOW()"); - $dataQuery = $staged->dataQuery() - ->innerJoin("BlogPost", "BlogPost" . $stage . ".ID = SiteTree" . $stage . ".ID") - ->where("PublishDate < NOW()"); - $staged = $staged->setDataQuery($dataQuery); - - } - return $staged; - } - - - - /** - * Augments (@link Hierarchy::liveChildren()} - * - * @param $staged DataList - * @param $showAll boolean - **/ - public function liveChildren($showAll = false, $onlyDeletedFromStage = false) { - $staged = parent::liveChildren($showAll, $onlyDeletedFromStage); - - $controller = Controller::curr(); - if($controller->class == "CMSPagesController" && in_array($controller->getAction(), array("treeview", "listview", "getsubtree"))) { - return $staged->exclude("ClassName", $this->owner->getExcludedSiteTreeClassNames()); - } else if(in_array($this->owner->ClassName, ClassInfo::subClassesFor("Blog")) && !Permission::check("VIEW_DRAFT_CONTENT")) { - $dataQuery = $staged->dataQuery() - ->innerJoin("BlogPost", "BlogPost_Live.ID = SiteTree_Live.ID") - ->where("PublishDate < NOW()"); - $staged = $staged->setDataQuery($dataQuery); - } - return $staged; } } \ No newline at end of file diff --git a/extensions/URLSegmentExtension.php b/extensions/URLSegmentExtension.php new file mode 100755 index 0000000..aced3fa --- /dev/null +++ b/extensions/URLSegmentExtension.php @@ -0,0 +1,48 @@ + +**/ +class URLSegmentExtension extends DataExtension { + + private static $db = array( + "URLSegment" => "Varchar(255)" + ); + + public function onBeforeWrite() { + $this->owner->generateURLSegment(); + } + + + + /** + * Generates a unique URLSegment from the title. + * + * @param $increment + * + * @return string URLSegment + **/ + public function generateURLSegment($increment = null) { + $filter = new URLSegmentFilter(); + $this->owner->URLSegment = $filter->filter($this->owner->Title); + if(is_int($increment)) $this->owner->URLSegment .= '-' . $increment; + + // Check to see if the URLSegment already exists + $duplicate = DataList::create($this->owner->ClassName)->filter(array( + "URLSegment" => $this->owner->URLSegment, + "BlogID" => $this->owner->BlogID + )); + if($this->owner->ID) $duplicate = $duplicate->exclude("ID", $this->owner->ID); + if($duplicate->count() > 0) { + $increment = is_int($increment) ? $increment + 1 : 0; + $this->owner->generateURLSegment((int) $increment); + } + return $this->owner->URLSegment; + } + +} \ No newline at end of file diff --git a/forms/AjaxTextField.php b/forms/AjaxTextField.php deleted file mode 100755 index 21a41cd..0000000 --- a/forms/AjaxTextField.php +++ /dev/null @@ -1,5 +0,0 @@ -getList()->add($obj); if(!$id) { - $gridField->setError(_t("GridFieldAddByDBField.ADDFAIL", "Unable to save " . $obj->Title . " to the database.")); + $gridField->setError(_t("GridFieldAddByDBField.ADDFAIL", "Unable to save " . $obj->Title . " to the database."), "error"); } } else { throw new UnexpectedValueException("Invalid field (" . $dbField . ") on " . $obj->ClassName . "."); diff --git a/forms/gridfield/GridFieldConfig_AddByDBField.php b/forms/gridfield/GridFieldConfig_AddByDBField.php deleted file mode 100755 index c5d5b9a..0000000 --- a/forms/gridfield/GridFieldConfig_AddByDBField.php +++ /dev/null @@ -1,15 +0,0 @@ -removeComponentsByType("GridFieldAddNewButton"); - - // Add new components - $this->addComponent(new GridFieldAddByDBField("buttons-before-left", $dataObjectField)); - } - -} \ No newline at end of file diff --git a/forms/gridfield/GridFieldSiteTreeAddNewButton.php b/forms/gridfield/GridFieldSiteTreeAddNewButton.php index 48f6149..b829367 100755 --- a/forms/gridfield/GridFieldSiteTreeAddNewButton.php +++ b/forms/gridfield/GridFieldSiteTreeAddNewButton.php @@ -9,7 +9,8 @@ * @package framework * @subpackage fields-gridfield */ -class GridFieldSiteTreeAddNewButton extends GridFieldAddNewButton { +class GridFieldSiteTreeAddNewButton extends GridFieldAddNewButton + implements GridField_ActionProvider { public function getHTMLFragments($gridField) { $singleton = singleton($gridField->getModelClass()); @@ -18,21 +19,99 @@ class GridFieldSiteTreeAddNewButton extends GridFieldAddNewButton { return array(); } + $parent = SiteTree::get()->byId(Controller::curr()->currentPageID()); + if(!$this->buttonName) { // provide a default button name, can be changed by calling {@link setButtonName()} on this component $objectName = $singleton->i18n_singular_name(); $this->buttonName = _t('GridField.Add', 'Add {name}', array('name' => $objectName)); } - $controller = $gridField->getForm()->getController(); - $data = new ArrayData(array( - 'NewLink' => $controller->LinkPageAdd("?ParentID=" . $controller->currentPageID()), - 'ButtonName' => $this->buttonName, - )); + $state = $gridField->State->GridFieldSiteTreeAddNewButton; + $state->currentPageID = $parent->ID; + $state->pageType = $parent->defaultChild(); + + $addAction = new GridField_FormAction($gridField, 'add', + sprintf(_t('GridField.ADD', "Add %s"), $singleton->i18n_singular_name()), 'add', 'add'); + $addAction->setAttribute('data-icon', 'add')->addExtraClass("no-ajax"); + + $allowedChildren = $parent->allowedChildren(); + $children = array(); + foreach($allowedChildren as $class) { + $children[$class] = singleton($class)->i18n_singular_name(); + } + + $pageTypes = DropdownField::create( + "PageType", + "Page Type", + $children, + $singleton->defaultChild() + ); + $pageTypes->setFieldHolderTemplate("BlogDropdownField_holder") + ->addExtraClass("gridfield-dropdown"); + + $forTemplate = new ArrayData(array()); + $forTemplate->Fields = new ArrayList(); + $forTemplate->Fields->push($pageTypes); + $forTemplate->Fields->push($addAction); + + Requirements::css(blog_dir() . "/css/cms.css"); + Requirements::javascript(blog_dir() . "/javascript/GridField.js"); return array( - $this->targetFragment => $data->renderWith('GridFieldAddNewbutton'), + $this->targetFragment => $forTemplate->renderWith("GridFieldSiteTreeAddNewButton") ); } + + + /** + * Provide actions to this component. + * + * @param $gridField GridField + * + * @return array + **/ + public function getActions($gridField) { + return array("add"); + } + + + + /** + * Handles the add action, but only acts as a wrapper for {@link CMSPageAddController::doAdd()} + * + * @param $gridFIeld GridFIeld + * @param $actionName string + * @param $arguments mixed + * @param $data array + **/ + public function handleAction(GridField $gridField, $actionName, $arguments, $data) { + if($actionName == "add") { + $tmpData = json_decode($data['BlogPost']['GridState'], true); + $tmpData = $tmpData['GridFieldSiteTreeAddNewButton']; + + $data = array( + "ParentID" => $tmpData['currentPageID'], + "PageType" => $tmpData['pageType'] + ); + + $controller = Injector::inst()->create("CMSPageAddController"); + + $form = $controller->AddForm(); + $form->loadDataFrom($data); + + $controller->doAdd($data, $form); + $response = $controller->getResponseNegotiator()->getResponse(); + + // Get the current record + $record = SiteTree::get()->byId($controller->currentPageID()); + if($record) { + $response->redirect(Director::absoluteBaseURL() . $record->CMSEditLink(), 301); + } + return $response; + + } + } + } \ No newline at end of file diff --git a/javascript/GridField.js b/javascript/GridField.js new file mode 100755 index 0000000..b2f7802 --- /dev/null +++ b/javascript/GridField.js @@ -0,0 +1,16 @@ +(function($){ + + $.entwine('ss', function($) { + $('.ss-gridfield .field .gridfield-dropdown').entwine({ + + onchange: function() { + var gridField = this.getGridField(); + var state = gridField.getState().GridFieldSiteTreeAddNewButton; + + state.pageType = this.val(); + gridField.setState("GridFieldSiteTreeAddNewButton", state); + } + }); + }); + +}(jQuery)); \ No newline at end of file diff --git a/model/BlogCategory.php b/model/BlogCategory.php index 24be276..279254b 100755 --- a/model/BlogCategory.php +++ b/model/BlogCategory.php @@ -18,8 +18,33 @@ class BlogCategory extends DataObject { "Blog" => "Blog", ); - private static $many_many = array( + private static $belongs_many_many = array( "BlogPosts" => "BlogPost", ); + private static $extensions = array( + "URLSegmentExtension", + ); + + + + public function getCMSFields() { + $fields = new FieldList( + TextField::create("Title", _t("BlogTag.FieldLabels.TITLE", "Title")) + ); + $this->extend("updateCMSFields", $fields); + return $fields; + } + + + + /** + * Returns a relative link to this category. + * + * @return string URL + **/ + public function getLink() { + return Controller::join_links($this->Blog()->Link(), "category", $this->URLSegment); + } + } \ No newline at end of file diff --git a/model/BlogTag.php b/model/BlogTag.php index 251363e..9eec41d 100755 --- a/model/BlogTag.php +++ b/model/BlogTag.php @@ -18,8 +18,30 @@ class BlogTag extends DataObject { "Blog" => "Blog", ); - private static $many_many = array( + private static $belongs_many_many = array( "BlogPosts" => "BlogPost", ); + private static $extensions = array( + "URLSegmentExtension", + ); + + public function getCMSFields() { + $fields = new FieldList( + TextField::create("Title", _t("BlogTag.FieldLabels.TITLE", "Title")) + ); + $this->extend("updateCMSFields", $fields); + return $fields; + } + + + /** + * Returns a relative URL for the tag link. + * + * @return string URL + **/ + public function getLink() { + return Controller::join_links($this->Blog()->Link(), "tag", $this->URLSegment); + } + } \ No newline at end of file diff --git a/page/Blog.php b/page/Blog.php index f72a098..cc23379 100755 --- a/page/Blog.php +++ b/page/Blog.php @@ -10,40 +10,22 @@ **/ class Blog extends Page { + private static $db = array( + "PostsPerPage" => "Int", + ); + private static $has_many = array( "Tags" => "BlogTag", - "Categories" => "BlogCategory" + "Categories" => "BlogCategory", ); private static $allowed_children = array( - "BlogPost" + "BlogPost", ); - - /** - * Enable archive. - * - * @var boolean - **/ - private static $archive_enabled = true; - - - /** - * Enable tags - * - * @var boolean - **/ - private static $tags_enabled = true; - - - /** - * Enable categories - * - * @var boolean - **/ - private static $categories_enabled = true; - - + private static $extensions = array( + "BlogFilter", + ); /** * Whether or not to show BlogPost's in a GridField. Usually this will be @@ -67,27 +49,37 @@ class Blog extends Page { $fields->addFieldToTab("Root.BlogPosts", $gridField); } - if($this->config()->get("categories_enabled")) { - $fields->addFieldToTab("Root." . _t("Blog.CATEGORIES", "Categories"), - GridField::create( - "Categories", - _t("Blog.FieldLabels.Categories", "Categories"), - $this->Categories(), - GridFieldConfig_AddByDBField::create() - ) - ); - } + // Create categories and tag config + $config = GridFieldConfig_RecordEditor::create(); + $config->removeComponentsByType("GridFieldAddNewButton"); + $config->addComponent(new GridFieldAddByDBField("buttons-before-left")); - if($this->config()->get("tags_enabled")) { - $fields->addFieldToTab("Root." . _t("Blog.TAGS", "Tags"), - GridField::create( - "Tags", - _t("Blog.FieldLabels.Tags", "Tags"), - $this->Tags(), - GridFieldConfig_AddByDBField::create() - ) - ); - } + $categories = GridField::create( + "Categories", + _t("Blog.FieldLabels.Categories", "Categories"), + $this->Categories(), + $config + ); + + $tags = GridField::create( + "Tags", + _t("Blog.FieldLabels.Tags", "Tags"), + $this->Tags(), + $config + ); + + $fields->addFieldsToTab("Root.BlogOptions", array( + $categories, + $tags + )); + + return $fields; + } + + + public function getSettingsFields() { + $fields = parent::getSettingsFields(); + $fields->addFieldToTab("Root.Settings", NumericField::create("PostsPerPage", _t("Blog.FieldLabels.POSTSPERPAGE", "Posts Per Page"))); return $fields; } @@ -118,7 +110,7 @@ class Blog extends Page { * @return DataList of BlogPost objects **/ public function getBlogPosts() { - return $this->AllChildren()->filter("ClassName", ClassInfo::subClassesFor("BlogPost")); + return BlogPost::get()->filter("ParentID", $this->ID); } } @@ -142,48 +134,208 @@ class Blog_Controller extends Page_Controller { ); private static $url_handlers = array( - 'tag/$Tag' => "tag", - 'category/$Category' => "category", + 'tag/$Tag!' => 'tag', + 'category/$Category!' => 'category', + 'archive/$Year!/$Month' => 'archive', ); + + /** + * The current Blog Post DataList query. + * + * @var DataList + **/ protected $blogPosts; + + public function index() { - $this->blogPosts = $this->AllChildren(); + $this->blogPosts = $this->getBlogPosts(); return $this->render(); } + + /** + * Renders an archive for a specificed date. This can be by year or year/month + * + * @return SS_HTTPResponse + **/ public function archive() { - return $this->render(); + $year = $this->getArchiveYear(); + $month = $this->getArchiveMonth(); + + // If an invalid month has been passed, we can return a 404. + if($this->request->param("Month") && !$month) { + return $this->httpError(404, "Not Found"); + } + + if($year) { + if($month) { + $startDate = $year . '-' . $month . '-01 00:00:00'; + if($month == 12) { + $endDate = ($year+1) . '-01-01 00:00:00'; + } else { + $endDate = $year . '-' . ($month + 1) . '-' . '01 00:00:00'; + } + } else { + $startDate = $year . '-01-01 00:00:00'; + $endDate = ($year+1) . '12-31 23:59:59'; + } + + // Ensure that we never fetch back unpublished future posts. + if(strtotime($endDate) > time()) { + $endDate = date('Y-m-d H:i:s'); + } + + $query = $this->getBlogPosts()->dataQuery(); + + $stage = $query->getQueryParam("Versioned.stage"); + if($stage) $stage = '_' . Convert::raw2sql($stage); + + $query->innerJoin("BlogPost", "`SiteTree" . $stage . "`.`ID` = `BlogPost" . $stage . "`.`ID`"); + $query->where("`PublishDate` >= '" . Convert::raw2sql($startDate) . "' + AND `PublishDate` < '" . Convert::raw2sql($endDate) . "'"); + + $this->blogPosts = $this->getBlogPosts()->setDataQuery($query); + return $this->render(); + } + return $this->httpError(404, "Not Found"); } + + /** + * Renders the blog posts for a given tag. + * + * @return SS_HTTPResponse + **/ public function tag() { + $tag = $this->getCurrentTag(); + if($tag) { + $this->blogPosts = $tag->BlogPosts(); + return $this->render(); + } + return $this->httpError(404, "Not Found"); + } + + + + /** + * Renders the blog posts for a given category + * + * @return SS_HTTPResponse + **/ + public function category() { + $category = $this->getCurrentCategory(); + if($category) { + $this->blogPosts = $category->BlogPosts(); + return $this->render(); + } + return $this->httpError(404, "Not Found"); + } + + + + /** + * Returns a list of paginated blog posts based on the blogPost dataList + * + * @return PaginatedList + **/ + public function PaginatedList() { + $posts = new PaginatedList($this->blogPosts); + + // If pagination is set to '0' then no pagination will be shown. + if($this->PostsPerPage > 0) $posts->setPageLength($this->PostsPerPage); + else $posts->setPageLength($this->getBlogPosts()->count()); + + $start = $this->request->getVar($posts->getPaginationGetVar()); + $posts->setPageStart($start); + + return $posts; + } + + + + /** + * Tag Getter for use in templates. + * + * @return BlogTag|null + **/ + public function getCurrentTag() { $tag = $this->request->param("Tag"); if($tag) { - $tag = $this->Tags()->filter("Title", $tag)->first(); - if($tag) { - $this->blogPosts = $this->AllChildren()->filter("ID", $tag->BlogPosts()->getIDList()); - return $this->render(); - } + return $this->dataRecord->Tags() + ->filter("URLSegment", $tag) + ->first(); } - return $this->httpError(404, "Not Found"); + return null; } - public function category() { + + + /** + * Category Getter for use in templates. + * + * @return BlogCategory|null + **/ + public function getCurrentCategory() { $category = $this->request->param("Category"); if($category) { - $category = $this->Categories()->filter("Title", $category)->first(); - if($category) { - $this->blogPosts = $this->AllChildren()->filter("ID", $category->BlogPosts()->getIDList()); - return $this->render(); - } + return $this->dataRecord->Categories() + ->filter("URLSegment", $category) + ->first(); } - return $this->httpError(404, "Not Found"); + return null; } - public function PaginatedPosts() { - return new PaginatedList($this->blogPosts); + + + /** + * Fetches the archive year from the url + * + * @return int|null + **/ + public function getArchiveYear() { + $year = $this->request->param("Year"); + if(preg_match("/^[0-9]{4}$/", $year)) { + return $year; + } + return null; } + + + + /** + * Fetches the archive money from the url. + * + * @return int|null + **/ + public function getArchiveMonth() { + $month = $this->request->param("Month"); + if(preg_match("/^[0-9]{1,2}$/", $month)) { + if($month > 0 && $month < 13) + return $month; + } + return null; + } + + + + public function getArchiveDate() { + $year = $this->getArchiveYear(); + $month = $this->getArchiveMonth(); + + if($year) { + if($month) { + $startDate = $year . '-' . $month . '-01 00:00:00'; + } else { + $startDate = $year . '-01-01 00:00:00'; + } + $date = new Date("ArchiveDate"); + $date->setValue($startDate); + return $date; + } + } + } \ No newline at end of file diff --git a/page/BlogPost.php b/page/BlogPost.php index 36f24b2..aa67c9f 100755 --- a/page/BlogPost.php +++ b/page/BlogPost.php @@ -17,6 +17,19 @@ class BlogPost extends Page { "PublishDate" => "SS_Datetime", ); + private static $has_one = array( + "FeaturedImage" => "Image", + ); + + private static $many_many = array( + "Categories" => "BlogCategory", + "Tags" => "BlogTag", + ); + + private static $defaults = array( + "ShowInMenus" => 0, + ); + /** * @var array @@ -25,12 +38,33 @@ class BlogPost extends Page { + /** + * Set the default sort to publish date + * + * @var string + **/ + private static $default_sort = "PublishDate DESC"; + + + + /** + * Add blog post filter to BlogPost + * + * @var array + **/ + private static $extensions = array( + "BlogPostFilter", + ); + + + /** * @var boolean **/ public static $can_be_root = false; + /** * This will display or hide the current class from the SiteTree. This * variable can be configured using YAML. @@ -40,16 +74,35 @@ class BlogPost extends Page { private static $show_in_site_tree = false; + public function getCMSFields() { $fields = parent::getCMSFields(); - $fields->insertBefore( - $publishDate = DatetimeField::create("PublishDate", _t("BlogPost.FieldLabels.PublishDate", "Publish Date")), + + // Add Publish date fields + $fields->insertAfter( + $publishDate = DatetimeField::create("PublishDate", _t("BlogPost.FieldLabels.PUBLISHDATE", "Publish Date")), "Content" ); - - // Publish date field config. $publishDate->getDateField()->setConfig("showcalendar", true); + // Add Categories & Tags fields + $categories = $this->Parent()->Categories()->map()->toArray(); + $categoriesField = ListboxField::create("Categories", _t("BlogPost.FieldLabels.CATEGORIES", "Categories"), $categories) + ->setMultiple(true); + $fields->insertAfter($categoriesField, "PublishDate"); + + $tags = $this->Parent()->Tags()->map()->toArray(); + $tagsField = ListboxField::create("Tags", _t("BlogPost.FieldLabels.TAGS", "Tags"), $tags) + ->setMultiple(true); + $fields->insertAfter($tagsField, "Categories"); + + // Add featured image + $fields->insertBefore( + $uploadField = UploadField::create("FeaturedImage", _t("BlogPost.FieldLabels.FEATUREDIMAGE", "Featured Image")), + "Content" + ); + $uploadField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif')); + return $fields; } @@ -84,11 +137,48 @@ class BlogPost extends Page { return true; } + + + /** + * Returns the post excerpt. + * + * @param $wordCount int - number of words to display + * + * @return string + **/ + public function getExcerpt($wordCount = 30) { + return $this->dbObject("Content")->LimitWordCount($wordCount); + } + + + + /** + * Returns a monthly archive link for the current blog post. + * + * @return string URL + **/ + public function getMonthlyArchiveLink() { + $date = $this->dbObject("PublishDate"); + return Controller::join_links($this->Parent()->Link("archive"), $date->format("Y"), $date->format("m")); + } + + + + /** + * Returns a yearly archive link for the current blog post. + * + * @return string URL + **/ + public function getYearlyArchiveLink() { + $date = $this->dbObject("PublishDate"); + return Controller::join_links($this->Parent()->Link("archive"), $date->format("Y")); + } + } /** - * An indivisual blog post. + * Blog Post controller * * @package silverstripe * @subpackage blog @@ -97,4 +187,4 @@ class BlogPost extends Page { **/ class BlogPost_Controller extends Page_Controller { -} \ No newline at end of file +} diff --git a/templates/Includes/BlogPagination.ss b/templates/Includes/BlogPagination.ss new file mode 100755 index 0000000..e321866 --- /dev/null +++ b/templates/Includes/BlogPagination.ss @@ -0,0 +1,21 @@ +<% if $PaginatedList.MoreThanOnePage %> + +<% end_if %> \ No newline at end of file diff --git a/templates/Includes/BlogSideBar.ss b/templates/Includes/BlogSideBar.ss new file mode 100755 index 0000000..c79b95c --- /dev/null +++ b/templates/Includes/BlogSideBar.ss @@ -0,0 +1,3 @@ + diff --git a/templates/Layout/Blog.ss b/templates/Layout/Blog.ss deleted file mode 100755 index 44af685..0000000 --- a/templates/Layout/Blog.ss +++ /dev/null @@ -1,18 +0,0 @@ -<% include SideBar %> -
-
-

$Title

-
$Content
- <% if BlogPosts %> -
    - <% loop BlogPosts %> -
  • $Title
  • - <% end_loop %> -
- <% else %> -

Unable to find any blog posts.

- <% end_if %> -
- $Form - $PageComments -
\ No newline at end of file diff --git a/templates/forms/BlogDropdownField_holder.ss b/templates/forms/BlogDropdownField_holder.ss new file mode 100755 index 0000000..3a740ea --- /dev/null +++ b/templates/forms/BlogDropdownField_holder.ss @@ -0,0 +1,3 @@ +
+ $Field +
diff --git a/templates/Includes/GridFieldAddByDBField.ss b/templates/forms/GridFieldAddByDBField.ss similarity index 100% rename from templates/Includes/GridFieldAddByDBField.ss rename to templates/forms/GridFieldAddByDBField.ss diff --git a/templates/forms/GridFieldSiteTreeAddNew.ss b/templates/forms/GridFieldSiteTreeAddNew.ss new file mode 100755 index 0000000..12fa97e --- /dev/null +++ b/templates/forms/GridFieldSiteTreeAddNew.ss @@ -0,0 +1,3 @@ +<% loop Fields %> + $Field +<% end_loop %> \ No newline at end of file diff --git a/templates/forms/GridFieldSiteTreeAddNewButton.ss b/templates/forms/GridFieldSiteTreeAddNewButton.ss new file mode 100755 index 0000000..6202e8f --- /dev/null +++ b/templates/forms/GridFieldSiteTreeAddNewButton.ss @@ -0,0 +1,3 @@ +<% loop Fields %> + $FieldHolder +<% end_loop %> \ No newline at end of file diff --git a/templates/widgets/BlogArchiveWidget.ss b/templates/widgets/BlogArchiveWidget.ss new file mode 100755 index 0000000..a5162c6 --- /dev/null +++ b/templates/widgets/BlogArchiveWidget.ss @@ -0,0 +1,9 @@ +<% if Archive %> + \ No newline at end of file diff --git a/templates/widgets/BlogCategoriesWidget.ss b/templates/widgets/BlogCategoriesWidget.ss new file mode 100755 index 0000000..298c683 --- /dev/null +++ b/templates/widgets/BlogCategoriesWidget.ss @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/templates/widgets/BlogRecentPostsWidget.ss b/templates/widgets/BlogRecentPostsWidget.ss new file mode 100755 index 0000000..c3bd5e2 --- /dev/null +++ b/templates/widgets/BlogRecentPostsWidget.ss @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/templates/widgets/BlogTagsWidget.ss b/templates/widgets/BlogTagsWidget.ss new file mode 100755 index 0000000..c83796c --- /dev/null +++ b/templates/widgets/BlogTagsWidget.ss @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/widgets/BlogArchiveWidget.php b/widgets/BlogArchiveWidget.php new file mode 100755 index 0000000..ad8181d --- /dev/null +++ b/widgets/BlogArchiveWidget.php @@ -0,0 +1,81 @@ + "Int", + "Type" => "Enum('Monthly, Yearly', 'Monthly')" + ); + + private static $defaults = array( + "NumberOfMonths" => 12 + ); + + private static $has_one = array( + "Blog" => "Blog", + ); + + public function getCMSFields() { + $fields = parent::getCMSFields(); + + $type = $this->dbObject("Type")->enumValues(); + foreach($type as $k => $v) { + $type[$k] = _t("BlogArchiveWidget." . strtoupper($v), $v); + } + + $fields->push(DropdownField::create("BlogID", _t("BlogArchiveWidget.FieldLabels.BLOG", "Blog"), Blog::get()->map())); + $fields->push(DropdownField::create("Type", _t("BlogArchiveWidget.FieldLabels.TYPE", "Type"), $type)); + $fields->push(NumericField::create("NumberToDisplay", _t("BlogArchiveWidget.LabelFields.NUMBERTODISPLAY", "No. to Display"))); + return $fields; + } + + + /** + * Returns a list of months where blog posts are present. + * + * @return DataList + **/ + public function getArchive() { + $query = $this->Blog()->getBlogPosts()->dataQuery(); + + if($this->Type == "Yearly") { + $query->groupBy("DATE_FORMAT(PublishDate, '%Y')"); + } else { + $query->groupBy("DATE_FORMAT(PublishDate, '%Y-%M')"); + } + + $articles = $this->Blog()->getBlogPosts()->setDataQuery($query); + if($this->NumberToDisplay > 0) $articles = $articles->limit($this->NumberToDisplay); + + $archive = new ArrayList(); + if($articles->count() > 0) { + foreach($articles as $article) { + if($this->Type == "Yearly") { + $year = date('Y', strtotime($article->PublishDate)); + $month = null; + $title = $year; + } else { + $year = date('Y', strtotime($article->PublishDate)); + $month = date('m', strtotime($article->PublishDate)); + $title = date('F Y', strtotime($article->PublishDate)); + } + $archive->push(new ArrayData(array( + "Title" => $title, + "Link" => Controller::join_links($this->Blog()->Link("archive"), $year, $month) + ))); + } + } + return $archive; + } + +} + +class BlogArchiveWidget_Controller extends Widget_Controller { + +} \ No newline at end of file diff --git a/widgets/BlogCategoriesWIdget.php b/widgets/BlogCategoriesWIdget.php new file mode 100755 index 0000000..aba9710 --- /dev/null +++ b/widgets/BlogCategoriesWIdget.php @@ -0,0 +1,35 @@ + "Blog", + ); + + public function getCMSFields() { + $fields = parent::getCMSFields(); + $fields->push(DropdownField::create("BlogID", _t("BlogCategoriesWidget.FieldLabels.BLOG", "Blog"), Blog::get()->map())); + return $fields; + } + + public function getCategories() { + $blog = $this->Blog(); + if($blog) { + return $blog->Categories(); + } + return array(); + } + +} + +class BlogCategoriesWidget_Controller extends Widget_Controller { + +} \ No newline at end of file diff --git a/widgets/BlogRecentPostsWidget.php b/widgets/BlogRecentPostsWidget.php new file mode 100755 index 0000000..9b05a81 --- /dev/null +++ b/widgets/BlogRecentPostsWidget.php @@ -0,0 +1,40 @@ + "Int", + ); + + private static $has_one = array( + "Blog" => "Blog", + ); + + public function getCMSFields() { + $fields = parent::getCMSFields(); + $fields->push(DropdownField::create("BlogID", _t("BlogCategoriesWidget.FieldLabels.BLOG", "Blog"), Blog::get()->map())); + $fields->push(NumericField::create("NumberOfPosts", _t("BlogRecentPostsWidget.FieldLabels.NUMBEROFPOSTS", "Number of Posts"))); + return $fields; + } + + public function getPosts() { + $blog = $this->Blog(); + if($blog) { + return $blog->getBlogPosts() + ->sort("PublishDate DESC") + ->limit($this->NumberOfPosts); + } + return array(); + } + +} + +class BlogRecentPostsWidget_Controller extends Widget_Controller { + +} \ No newline at end of file diff --git a/widgets/BlogTagsWidget.php b/widgets/BlogTagsWidget.php new file mode 100755 index 0000000..dc0fef2 --- /dev/null +++ b/widgets/BlogTagsWidget.php @@ -0,0 +1,35 @@ + "Blog", + ); + + public function getCMSFields() { + $fields = parent::getCMSFields(); + $fields->push(DropdownField::create("BlogID", _t("BlogCategoriesWidget.FieldLabels.BLOG", "Blog"), Blog::get()->map())); + return $fields; + } + + public function getTags() { + $blog = $this->Blog(); + if($blog) { + return $blog->Tags(); + } + return array(); + } + +} + +class BlogTagsWidget_Controller extends Widget_Controller { + +} \ No newline at end of file