$Title
- - <% if $FeaturedImage %> -$FeaturedImage.setWidth(795)
- <% end_if %> - -diff --git a/.gitignore b/.gitignore
index a5ffac4..3b7b7c6 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.ssh/*
.bash*
.profile
-vendor/*
+/vendor/*
.sass-cache/*
+/node_modules/
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
index 61b0c9f..de09355 100644
--- a/.scrutinizer.yml
+++ b/.scrutinizer.yml
@@ -6,4 +6,4 @@ checks:
duplication: true
filter:
- paths: [code/*, tests/*]
+ paths: [src/*, tests/*]
diff --git a/.travis.yml b/.travis.yml
index 41abb51..f64e3c1 100755
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,8 +12,6 @@ before_install:
env:
global:
- - DB=MYSQL CORE_RELEASE=3.1
-
# Turn coverage off by default, as it's expensive time wise
- COVERAGE=0
@@ -21,33 +19,30 @@ env:
- MODULE_PATH=blog
matrix:
- allow_failures:
- - php: hhvm-nightly
include:
- - php: 5.6
- env: DB=MYSQL COVERAGE=1
- - php: 5.5
- env: DB=MYSQL
- - php: 5.6
- env: DB=PGSQL
- - php: 5.6
- env: DB=MYSQL CORE_RELEASE=3.2
- - php: 5.6
- env: DB=PGSQL CORE_RELEASE=3.2
- - php: 5.4
- env: DB=SQLITE
- - php: 5.3
- env: DB=MYSQL
- - php: hhvm
- env: DB=MYSQL
+ - php: 7.1
+ env: DB=MYSQL CORE_RELEASE=4 COVERAGE=1
+ - php: 5.5
+ env: DB=MYSQL CORE_RELEASE=4
+
+ - php: 5.6
+ env: DB=MYSQL CORE_RELEASE=4
+ - php: 5.6
+ env: DB=PGSQL CORE_RELEASE=4
+ - php: 5.6
+ env: DB=SQLITE CORE_RELEASE=4
+
+ - php: 7.0
+ env: DB=MYSQL CORE_RELEASE=4
before_script:
- phpenv rehash
- composer self-update || true
- - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
+ - git clone git://github.com/silverstripe/silverstripe-travis-support.git ~/travis-support
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require "silverstripe/comments" --require "silverstripe/widgets"
- cd ~/builds/ss
+ - mv "$MODULE_PATH/phpunit.xml.dist" .
#Execute tests with or without coverage
script:
@@ -57,9 +52,8 @@ script:
# Execute tests with coverage. Do this for a small
- "if [ \"$COVERAGE\" = \"1\" ]; then vendor/bin/phpunit --coverage-clover=coverage.clover $MODULE_PATH/tests/; fi"
-#Upload coverage even if there is a failure
-after_script:
+# Upload code coverage when tests pass
+after_success:
- "if [ \"$COVERAGE\" = \"1\" ]; then mv coverage.clover ~/build/$TRAVIS_REPO_SLUG/; fi"
- cd ~/build/$TRAVIS_REPO_SLUG
- - wget https://scrutinizer-ci.com/ocular.phar
- - "if [ \"$COVERAGE\" = \"1\" ]; then travis_retry codecov && travis_retry php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi"
+ - "if [ \"$COVERAGE\" = \"1\" ]; then travis_retry codecov; fi"
diff --git a/.upgrade.yml b/.upgrade.yml
new file mode 100644
index 0000000..813650c
--- /dev/null
+++ b/.upgrade.yml
@@ -0,0 +1,33 @@
+mappings:
+ GridFieldCategorisationConfig: SilverStripe\Blog\Admin\GridFieldCategorisationConfig
+ GridFieldFormAction: SilverStripe\Blog\Admin\GridFieldFormAction
+ GridFieldMergeAction: SilverStripe\Blog\Admin\GridFieldMergeAction
+ BlogCommentExtension: SilverStripe\Blog\Model\BlogCommentExtension
+ BlogFilter: SilverStripe\Blog\Model\BlogFilter
+ BlogFilter_GridField: SilverStripe\Blog\Model\BlogFilter\BlogFilterGridField
+ BlogMemberExtension: SilverStripe\Blog\Model\BlogMemberExtension
+ BlogPostFilter: SilverStripe\Blog\Model\BlogPostFilter
+ BlogPostNotifications: SilverStripe\Blog\Model\BlogPostNotifications
+ Blog: SilverStripe\Blog\Model\Blog
+ Blog_Controller: SilverStripe\Blog\Controllers\BlogController
+ BlogController: SilverStripe\Blog\Controllers\BlogController
+ BlogCategory: SilverStripe\Blog\Model\BlogCategory
+ BlogPost: SilverStripe\Blog\Model\BlogPost
+ BlogPost_Controller: SilverStripe\Blog\Controllers\BlogPostController
+ BlogPostController: SilverStripe\Blog\Controllers\BlogPostController
+ BlogTag: SilverStripe\Blog\Model\BlogTag
+ CategorisationObject: SilverStripe\Blog\Model\CategorisationObject
+ BlogAdminSidebar: SilverStripe\Blog\Forms\BlogAdminSidebar
+ GridFieldAddByDBField: SilverStripe\Blog\Forms\GridField\GridFieldAddByDBField
+ GridFieldBlogPostState: SilverStripe\Blog\Forms\GridField\GridFieldBlogPostState
+ GridFieldConfig_BlogPost: SilverStripe\Blog\Forms\GridField\GridFieldConfig_BlogPost
+ BlogArchiveWidget: SilverStripe\Blog\Widgets\BlogArchiveWidget
+ BlogArchiveWidget_Controller: SilverStripe\Blog\Widgets\BlogArchiveWidgetController
+ BlogCategoriesWidget: SilverStripe\Blog\Widgets\BlogCategoriesWidget
+ BlogCategoriesWidget_Controller: SilverStripe\Blog\Widgets\BlogCategoriesWidgetController
+ BlogRecentPostsWidget: SilverStripe\Blog\Widgets\BlogRecentPostsWidget
+ BlogRecentPostsWidget_Controller: SilverStripe\Blog\Widgets\BlogRecentPostsWidgetController
+ BlogTagsCloudWidget: SilverStripe\Blog\Widgets\BlogTagsCloudWidget
+ BlogTagsCloudWidget_Controller: SilverStripe\Blog\Widgets\BlogTagsCloudWidgetController
+ BlogTagsWidget: SilverStripe\Blog\Widgets\BlogTagsWidget
+ BlogTagsWidget_Controller: SilverStripe\Blog\Widgets\BlogTagsWidgetController
diff --git a/README.md b/README.md
index a612d19..800304f 100755
--- a/README.md
+++ b/README.md
@@ -10,16 +10,16 @@
## Documentation
-[User guide](docs/en/userguide/index.md)
-[Developer documentation](docs/en/index.md)
+* [User guide](docs/en/userguide/index.md)
+* [Developer documentation](docs/en/index.md)
## Requirements
```
-silverstripe/cms: ^3.1
-silverstripe/lumberjack: ^1.1
-silverstripe/tagfield: ^1.0
+silverstripe/cms: ^4.0
+silverstripe/lumberjack: ^2.0
+silverstripe/tagfield: ^2.0
```
### Suggested Modules
@@ -35,8 +35,12 @@ silverstripe/comments: *
composer require silverstripe/blog
```
-## Upgrading legacy blog to 2.x
+## Upgrading
+
+### Upgrading from 2.x to 3.x
+
+Aside from the framework and CMS upgrades required the blog module should not require anything extra to be completed.
+
+### Upgrading legacy blog to 2.x
If you're upgrading from blog version 1.0 to 2.x you will need to run the `BlogMigrationTask`. Run the task using `dev/tasks/BlogMigrationTask` either via the browser or sake CLI to migrate your legacy blog to the new version data structure.
-
-
diff --git a/_config.php b/_config.php
index d8ae592..aded448 100755
--- a/_config.php
+++ b/_config.php
@@ -1,8 +1,8 @@
-removeComponentsByType('GridFieldAddNewButton');
-
- $this->addComponent(
- new GridFieldAddByDBField('buttons-before-left')
- );
-
- $this->addComponent(
- new GridFieldMergeAction($mergeRecords, $parentType, $parentMethod, $childMethod)
- );
-
- /**
- * @var GridFieldDataColumns $columns
- */
- $columns = $this->getComponentByType('GridFieldDataColumns');
-
- $columns->setFieldFormatting(array(
- 'BlogPostsCount' => function ($value, CategorisationObject $item) {
- return $item->BlogPosts()->Count();
- }
- ));
-
- $this->changeColumnOrder();
- }
-
- /**
- * Reorders GridField columns so that Actions is last.
- */
- protected function changeColumnOrder()
- {
- /**
- * @var GridFieldDataColumns $columns
- */
- $columns = $this->getComponentByType('GridFieldDataColumns');
-
- $columns->setDisplayFields(array(
- 'Title' => 'Title',
- 'BlogPostsCount' => 'Posts',
- 'MergeAction' => 'MergeAction',
- 'Actions' => 'Actions',
- ));
- }
-}
diff --git a/code/compat/pages/BlogEntry.php b/code/compat/pages/BlogEntry.php
deleted file mode 100644
index 190d475..0000000
--- a/code/compat/pages/BlogEntry.php
+++ /dev/null
@@ -1,112 +0,0 @@
- 'SS_Datetime',
- 'Author' => 'Text',
- 'Tags' => 'Text',
- );
-
- /**
- * {@inheritdoc}
- */
- public function canCreate($member = null)
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function up()
- {
-
- //Migrate comma separated tags into BlogTag objects.
- foreach ($this->TagNames() as $tag) {
- $existingTag = BlogTag::get()->filter(array('Title' => $tag, 'BlogID' => $this->ParentID));
- if ($existingTag->count()) {
- //if tag already exists we will simply add it to this post.
- $tagObject = $existingTag->First();
- } else {
- //if the tag is now we create it and add it to this post.
- $tagObject = new BlogTag();
- $tagObject->Title = $tag;
- $tagObject->BlogID = $this->ParentID;
- $tagObject->write();
- }
-
- if ($tagObject) {
- $this->Tags()->add($tagObject);
- }
- }
-
- //Store if the original entity was published or not (draft)
- $published = $this->IsPublished();
- // If a user has subclassed BlogEntry, it should not be turned into a BlogPost.
- if ($this->ClassName === 'BlogEntry') {
- $this->ClassName = 'BlogPost';
- $this->RecordClassName = 'BlogPost';
- }
- //Migrate these key data attributes
- $this->PublishDate = $this->Date;
- $this->AuthorNames = $this->Author;
- $this->InheritSideBar = true;
-
- //Write and additionally publish the item if it was published before.
- $this->write();
- if ($published) {
- $this->publish('Stage', 'Live');
- $message = "PUBLISHED: ";
- } else {
- $message = "DRAFT: ";
- }
-
- return $message . $this->Title;
- }
-
- /**
- * Safely split and parse all distinct tags assigned to this BlogEntry.
- *
- * @deprecated since version 2.0
- *
- * @return array
- */
- public function TagNames()
- {
- $tags = preg_split('/\s*,\s*/', trim($this->Tags));
-
- $results = array();
-
- foreach ($tags as $tag) {
- if ($tag) {
- $results[mb_strtolower($tag)] = $tag;
- }
- }
-
- return $results;
- }
-}
-
-/**
- * @deprecated since version 2.0
- */
-class BlogEntry_Controller extends BlogPost_Controller
-{
-}
diff --git a/code/compat/pages/BlogHolder.php b/code/compat/pages/BlogHolder.php
deleted file mode 100644
index 49bc287..0000000
--- a/code/compat/pages/BlogHolder.php
+++ /dev/null
@@ -1,77 +0,0 @@
- 'Boolean',
- 'ShowFullEntry' => 'Boolean',
- );
-
- /**
- * @var array
- */
- private static $has_one = array(
- 'Owner' => 'Member',
- );
-
- /**
- * {@inheritdoc}
- */
- public function canCreate($member = null)
- {
- return false;
- }
-
-
- //Overload these to stop the Uncaught Exception: Object->__call(): the method 'parent' does not exist on 'BlogHolder' error.
- public function validURLSegment()
- {
- return true;
- }
- public function syncLinkTracking()
- {
- return null;
- }
-
- /**
- * {@inheritdoc}
- */
- public function up()
- {
- $published = $this->IsPublished();
-
- if ($this->ClassName === 'BlogHolder') {
- $this->ClassName = 'Blog';
- $this->RecordClassName = 'Blog';
- $this->PostsPerPage = 10;
- $this->write();
- }
-
- if ($published) {
- $this->publish('Stage', 'Live');
- $message = "PUBLISHED: ";
- } else {
- $message = "DRAFT: ";
- }
-
- return $message . $this->Title;
- }
-}
-
-/**
- * @deprecated since version 2.0
- */
-class BlogHolder_Controller extends BlogTree_Controller
-{
-}
diff --git a/code/compat/pages/BlogTree.php b/code/compat/pages/BlogTree.php
deleted file mode 100644
index 0998de2..0000000
--- a/code/compat/pages/BlogTree.php
+++ /dev/null
@@ -1,56 +0,0 @@
- 'Varchar(255)',
- 'LandingPageFreshness' => 'Varchar',
- );
-
- /**
- * {@inheritdoc}
- */
- public function canCreate($member = null)
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function up()
- {
- $published = $this->IsPublished();
- if ($this->ClassName === 'BlogTree') {
- $this->ClassName = 'Page';
- $this->RecordClassName = 'Page';
- $this->write();
- }
- if ($published) {
- $this->publish('Stage', 'Live');
- $message = "PUBLISHED: ";
- } else {
- $message = "DRAFT: ";
- }
-
- return $message . $this->Title;
- }
-}
-
-/**
- * @deprecated since version 2.0
- */
-class BlogTree_Controller extends Page_Controller
-{
-}
diff --git a/code/compat/tasks/BlogMigrationTask.php b/code/compat/tasks/BlogMigrationTask.php
deleted file mode 100644
index 143fb7c..0000000
--- a/code/compat/tasks/BlogMigrationTask.php
+++ /dev/null
@@ -1,92 +0,0 @@
-message('Migrating legacy blog records');
-
- foreach ($classes as $class) {
- $this->upClass($class);
- }
- }
-
- /**
- * @param string $text
- */
- protected function message($text)
- {
- if (Controller::curr() instanceof DatabaseAdmin) {
- DB::alteration_message($text, 'obsolete');
- } else {
- echo $text . "
";
- }
- }
-
- /**
- * Migrate records of a single class
- *
- * @param string $class
- * @param null|string $stage
- */
- protected function upClass($class)
- {
- if (!class_exists($class)) {
- return;
- }
-
- if (is_subclass_of($class, 'SiteTree')) {
- $items = SiteTree::get()->filter('ClassName', $class);
- } else {
- $items = $class::get();
- }
-
- if ($count = $items->count()) {
- $this->message(
- sprintf(
- 'Migrating %s legacy %s records.',
- $count,
- $class
- )
- );
-
- foreach ($items as $item) {
- $cancel = $item->extend('onBeforeUp');
-
- if ($cancel && min($cancel) === false) {
- continue;
- }
-
- /**
- * @var MigratableObject $item
- */
- $result = $item->up();
- $this->message($result);
-
- $item->extend('onAfterUp');
- }
- }
- }
-
- /**
- * {@inheritdoc}
- */
- public function down()
- {
- $this->message('BlogMigrationTask::down() not implemented');
- }
-}
diff --git a/code/compat/tasks/MigratableObject.php b/code/compat/tasks/MigratableObject.php
deleted file mode 100644
index 2c747a8..0000000
--- a/code/compat/tasks/MigratableObject.php
+++ /dev/null
@@ -1,9 +0,0 @@
- 'Varchar',
- );
-
- /**
- * @var array
- */
- private static $only_available_in = array(
- 'none',
- );
-
- /**
- * {@inheritdoc}
- */
- public function canCreate($member = null)
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function up()
- {
- if ($this->DisplayMode) {
- $this->ArchiveType = 'Monthly';
-
- if ($this->DisplayMode === 'year') {
- $this->ArchiveType = 'Yearly';
- }
- }
-
- $this->ClassName = 'BlogArchiveWidget';
- $this->write();
- return "Migrated " . $this->ArchiveType . " archive widget";
- }
-}
diff --git a/code/compat/widgets/TagCloudWidget.php b/code/compat/widgets/TagCloudWidget.php
deleted file mode 100644
index a527ddd..0000000
--- a/code/compat/widgets/TagCloudWidget.php
+++ /dev/null
@@ -1,47 +0,0 @@
- 'Varchar',
- 'Limit' => 'Int',
- 'Sortby' => 'Varchar',
- );
-
- /**
- * @var array
- */
- private static $only_available_in = array(
- 'none',
- );
-
- /**
- * {@inheritdoc}
- */
- public function canCreate($member = null)
- {
- return false;
- }
-
- /**
- * {@inheritdoc}
- */
- public function up()
- {
- $this->ClassName = 'BlogTagsWidget';
- $this->write();
- return "Migrated " . $this->Title . " widget";
- }
-}
diff --git a/code/extensions/BlogPostFilter.php b/code/extensions/BlogPostFilter.php
deleted file mode 100644
index 1795bc8..0000000
--- a/code/extensions/BlogPostFilter.php
+++ /dev/null
@@ -1,45 +0,0 @@
-addWhere(sprintf('"PublishDate" < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
- }
- }
-
- /**
- * This is a fix so that when we try to fetch subclasses of BlogPost, lazy loading includes the
- * BlogPost table in its query. Leaving this table out means the default sort order column
- * PublishDate causes an error.
- *
- * @see https://github.com/silverstripe/silverstripe-framework/issues/1682
- *
- * @param SQLQuery $query
- * @param mixed $dataQuery
- * @param mixed $parent
- */
- public function augmentLoadLazyFields(SQLQuery &$query, &$dataQuery, $parent)
- {
- $dataQuery->innerJoin('BlogPost', '"SiteTree"."ID" = "BlogPost"."ID"');
- }
-}
diff --git a/code/extensions/URLSegmentExtension.php b/code/extensions/URLSegmentExtension.php
deleted file mode 100644
index 2daba19..0000000
--- a/code/extensions/URLSegmentExtension.php
+++ /dev/null
@@ -1,78 +0,0 @@
- 'Varchar(255)',
- );
-
- /**
- * {@inheritdoc}
- */
- public function onBeforeWrite()
- {
- if ($this->owner->BlogID) {
- $this->owner->generateURLSegment();
- }
- }
-
- /**
- * Generates a unique URLSegment from the title.
- *
- * @param int $increment
- *
- * @return string
- */
- public function generateURLSegment($increment = null)
- {
- $filter = new URLSegmentFilter();
-
- // Setting this to on. Because of the UI flow, it would be quite a lot of work
- // to support turning this off. (ie. the add by title flow would not work).
- // If this becomes a problem we can approach it then.
- // @see https://github.com/silverstripe/silverstripe-blog/issues/376
- $filter->setAllowMultibyte(true);
-
- $this->owner->URLSegment = $filter->filter($this->owner->Title);
-
- if (is_int($increment)) {
- $this->owner->URLSegment .= '-' . $increment;
- }
-
- // Postgres use '' instead of 0 as an emtpy blog ID
- // Without this all the tests fail
- if (!$this->owner->BlogID) {
- $this->owner->BlogID = 0;
- }
-
- $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) {
- if (is_int($increment)) {
- $increment += 1;
- } else {
- $increment = 0;
- }
-
- $this->owner->generateURLSegment((int) $increment);
- }
-
- return $this->owner->URLSegment;
- }
-}
diff --git a/code/model/BlogCategory.php b/code/model/BlogCategory.php
deleted file mode 100644
index a678e40..0000000
--- a/code/model/BlogCategory.php
+++ /dev/null
@@ -1,188 +0,0 @@
- 'Varchar(255)',
- );
-
- /**
- * @var array
- */
- private static $has_one = array(
- 'Blog' => 'Blog',
- );
-
- /**
- * @var array
- */
- private static $belongs_many_many = array(
- 'BlogPosts' => 'BlogPost',
- );
-
- /**
- * @var array
- */
- private static $extensions = array(
- 'URLSegmentExtension',
- );
-
- /**
- * @return DataList
- */
- public function BlogPosts()
- {
- $blogPosts = parent::BlogPosts();
-
- $this->extend("updateGetBlogPosts", $blogPosts);
-
- return $blogPosts;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getCMSFields()
- {
- $fields = new FieldList(
- TextField::create('Title', _t('BlogCategory.Title', 'Title'))
- );
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function validate()
- {
- $validation = parent::validate();
- if($validation->valid()) {
- // Check for duplicate categories
- $blog = $this->Blog();
- if($blog && $blog->exists()) {
- $existing = $blog->Categories()->filter('Title', $this->Title);
- if($this->ID) {
- $existing = $existing->exclude('ID', $this->ID);
- }
- if($existing->count() > 0) {
- $validation->error(_t(
- 'BlogCategory.Duplicate',
- 'A blog category already exists with that name'
- ), BlogCategory::DUPLICATE_EXCEPTION);
- }
- }
- }
- return $validation;
- }
-
- /**
- * Returns a relative link to this category.
- *
- * @return string
- */
- public function getLink()
- {
- return Controller::join_links($this->Blog()->Link(), 'category', $this->URLSegment);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canView($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canView($member);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canCreate($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- $permission = Blog::config()->grant_user_permission;
-
- return Permission::checkMember($member, $permission);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canDelete($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canEdit($member);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canEdit($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canEdit($member);
- }
-}
diff --git a/code/model/BlogTag.php b/code/model/BlogTag.php
deleted file mode 100644
index 47c9e57..0000000
--- a/code/model/BlogTag.php
+++ /dev/null
@@ -1,189 +0,0 @@
- 'Varchar(255)',
- );
-
- /**
- * @var array
- */
- private static $has_one = array(
- 'Blog' => 'Blog',
- );
-
- /**
- * @var array
- */
- private static $belongs_many_many = array(
- 'BlogPosts' => 'BlogPost',
- );
-
- /**
- * @var array
- */
- private static $extensions = array(
- 'URLSegmentExtension',
- );
-
- /**
- * @return DataList
- */
- public function BlogPosts()
- {
- $blogPosts = parent::BlogPosts();
-
- $this->extend("updateGetBlogPosts", $blogPosts);
-
- return $blogPosts;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getCMSFields()
- {
- $fields = new FieldList(
- TextField::create('Title', _t('BlogTag.Title', 'Title'))
- );
-
- $this->extend('updateCMSFields', $fields);
-
- return $fields;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function validate()
- {
- $validation = parent::validate();
- if($validation->valid()) {
- // Check for duplicate tags
- $blog = $this->Blog();
- if($blog && $blog->exists()) {
- $existing = $blog->Tags()->filter('Title', $this->Title);
- if($this->ID) {
- $existing = $existing->exclude('ID', $this->ID);
- }
- if($existing->count() > 0) {
- $validation->error(_t(
- 'BlogTag.Duplicate',
- 'A blog tags already exists with that name'
- ), BlogTag::DUPLICATE_EXCEPTION);
- }
- }
- }
- return $validation;
- }
-
- /**
- * Returns a relative URL for the tag link.
- *
- * @return string
- */
- public function getLink()
- {
- return Controller::join_links($this->Blog()->Link(), 'tag', $this->URLSegment);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canView($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canView($member);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canCreate($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- $permission = Blog::config()->grant_user_permission;
-
- return Permission::checkMember($member, $permission);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canDelete($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canEdit($member);
- }
-
- /**
- * Inherits from the parent blog or can be overwritten using a DataExtension.
- *
- * @param null|Member $member
- *
- * @return bool
- */
- public function canEdit($member = null)
- {
- $extended = $this->extendedCan(__FUNCTION__, $member);
-
- if ($extended !== null) {
- return $extended;
- }
-
- return $this->Blog()->canEdit($member);
- }
-}
diff --git a/code/widgets/BlogCategoriesWidget.php b/code/widgets/BlogCategoriesWidget.php
deleted file mode 100644
index 1429dab..0000000
--- a/code/widgets/BlogCategoriesWidget.php
+++ /dev/null
@@ -1,100 +0,0 @@
- 'Int',
- 'Order' => 'Varchar',
- 'Direction' => 'Varchar',
- );
-
- /**
- * @var array
- */
- private static $has_one = array(
- 'Blog' => 'Blog',
- );
-
- /**
- * {@inheritdoc}
- */
- public function getCMSFields()
- {
- $this->beforeUpdateCMSFields(function (FieldList $fields) {
- $fields[] = DropdownField::create(
- 'BlogID', _t('BlogCategoriesWidget.Blog', 'Blog'), Blog::get()->map()
- );
-
- $fields[] = NumericField::create(
- 'Limit', _t('BlogCategoriesWidget.Limit.Label', 'Limit'), 0
- )
- ->setDescription(_t('BlogCategoriesWidget.Limit.Description', 'Limit the number of categories shown by this widget (set to 0 to show all categories).'))
- ->setMaxLength(3);
-
- $fields[] = DropdownField::create(
- 'Order', _t('BlogCategoriesWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastEdited' => 'Updated')
- )
- ->setDescription(_t('BlogCategoriesWidget.Sort.Description', 'Change the order of categories shown by this widget.'));
-
- $fields[] = DropdownField::create(
- 'Direction', _t('BlogCategoriesWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
- )
- ->setDescription(_t('BlogCategoriesWidget.Direction.Description', 'Change the direction of ordering of categories shown by this widget.'));
- });
-
- return parent::getCMSFields();
- }
-
- /**
- * @return DataList
- */
- public function getCategories()
- {
- $blog = $this->Blog();
-
- if (!$blog) {
- return array();
- }
-
- $query = $blog->Categories();
-
- if ($this->Limit) {
- $query = $query->limit(Convert::raw2sql($this->Limit));
- }
-
- if ($this->Order && $this->Direction) {
- $query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
- }
-
- return $query;
- }
-}
-
-class BlogCategoriesWidget_Controller extends Widget_Controller
-{
-}
diff --git a/composer.json b/composer.json
index fe52322..dbaf739 100755
--- a/composer.json
+++ b/composer.json
@@ -1,39 +1,45 @@
{
- "name": "silverstripe/blog",
- "description": "A fresh take on blogging in Silverstripe set out to tackle the issue of a cluttered Site Tree.",
- "keywords": [
- "silverstripe",
- "blog",
- "news"
- ],
- "type": "silverstripe-module",
- "require": {
- "silverstripe/cms": "^3.1.0",
- "silverstripe/lumberjack": "~1.1",
- "silverstripe/tagfield": "^1.0"
- },
- "require-dev": {
- "phpunit/PHPUnit": "~3.7@stable"
- },
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
- "license": "BSD-2-Clause",
- "authors": [
- {
- "name": "Michael Strong",
- "email": "github@michaelstrong.co.uk"
- }
- ],
- "suggest": {
- "silverstripe/widgets": "Some widgets come with the blog which are compatible with the widgets module.",
- "silverstripe/comments": "This module adds comments to your blog."
- },
- "replace": {
- "micmania1/silverstripe-blog": "*"
- },
- "minimum-stability": "dev",
- "prefer-stable": true
+ "name": "silverstripe/blog",
+ "description": "A fresh take on blogging in Silverstripe set out to tackle the issue of a cluttered Site Tree.",
+ "keywords": [
+ "silverstripe",
+ "blog",
+ "news"
+ ],
+ "type": "silverstripe-module",
+ "require": {
+ "silverstripe/cms": "^4.0",
+ "silverstripe/lumberjack": "^2.0",
+ "silverstripe/tagfield": "^2.0"
+ },
+ "require-dev": {
+ "phpunit/PHPUnit": "~4.8"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "SilverStripe\\Blog\\": "src/",
+ "SilverStripe\\Blog\\Tests\\": "tests/"
+ }
+ },
+ "license": "BSD-2-Clause",
+ "authors": [
+ {
+ "name": "Michael Strong",
+ "email": "github@michaelstrong.co.uk"
+ }
+ ],
+ "suggest": {
+ "silverstripe/widgets": "Some widgets come with the blog which are compatible with the widgets module.",
+ "silverstripe/comments": "This module adds comments to your blog."
+ },
+ "replace": {
+ "micmania1/silverstripe-blog": "*"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
}
diff --git a/config.rb b/config.rb
deleted file mode 100755
index 31c7f33..0000000
--- a/config.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# Require any additional compass plugins here.
-
-# Set this to the root of your project when deployed:
-http_path = "/"
-css_dir = "css"
-sass_dir = "scss"
-javascripts_dir = "javascript"
-
-# You can select your preferred output style here (can be overridden via the command line):
-# output_style = :expanded or :nested or :compact or :compressed
-
-# To enable relative paths to assets via compass helper functions. Uncomment:
-relative_assets = true
-
-# To disable debugging comments that display the original location of your selectors. Uncomment:
-line_comments = false
-
-
-# If you prefer the indented syntax, you might want to regenerate this
-# project again passing --syntax sass, or you can uncomment this:
-# preferred_syntax = :sass
-# and then run:
-# sass-convert -R --from scss --to sass scss scss && rm -rf sass && mv scss sass
diff --git a/css/blog.css b/css/blog.css
index fe370bc..a89a5eb 100644
--- a/css/blog.css
+++ b/css/blog.css
@@ -1,58 +1,43 @@
.no-sidebar .content-container.size3of4 {
- width: 75%;
-}
+ width: 75%; }
.blog-entry .post-image img {
- width: 98.75%;
-}
+ width: 98.75%; }
.blog-sidebar .WidgetHolder ul {
- margin-left: 0;
-}
-.blog-sidebar .WidgetHolder ul li {
- list-style-type: none;
-}
+ margin-left: 0; }
+ .blog-sidebar .WidgetHolder ul li {
+ list-style-type: none; }
+
ul.blogTagCloud {
list-style-type: none;
- clear: both;
-}
-ul.blogTagCloud li {
- float: left;
- display: inline;
- padding-right: 8px;
-}
-ul.blogTagCloud li a span {
+ clear: both; }
+ ul.blogTagCloud li {
float: left;
- line-height: 30px; text-align: center;
- padding: 0px;
-}
-ul.blogTagCloud .tagCount10 {
- font-size: 26pt;
-}
-ul.blogTagCloud .tagCount9 {
- font-size: 24pt;
-}
-ul.blogTagCloud .tagCount8 {
- font-size: 22pt;
-}
-ul.blogTagCloud .tagCount7 {
- font-size: 20pt;
-}
-ul.blogTagCloud .tagCount6 {
- font-size: 18pt;
-}
-ul.blogTagCloud .tagCount5 {
- font-size: 16pt;
-}
-ul.blogTagCloud .tagCount4 {
- font-size: 14pt;
-}
-ul.blogTagCloud .tagCount3 {
- font-size: 12pt;
-}
-ul.blogTagCloud .tagCount2 {
- font-size: 10pt;
-}
-ul.blogTagCloud .tagCount1 {
- font-size: 8pt;
-}
+ display: inline;
+ padding-right: 8px; }
+ ul.blogTagCloud li a span {
+ float: left;
+ line-height: 30px;
+ text-align: center;
+ padding: 0px; }
+ ul.blogTagCloud .tagCount10 {
+ font-size: 26pt; }
+ ul.blogTagCloud .tagCount9 {
+ font-size: 24pt; }
+ ul.blogTagCloud .tagCount8 {
+ font-size: 22pt; }
+ ul.blogTagCloud .tagCount7 {
+ font-size: 20pt; }
+ ul.blogTagCloud .tagCount6 {
+ font-size: 18pt; }
+ ul.blogTagCloud .tagCount5 {
+ font-size: 16pt; }
+ ul.blogTagCloud .tagCount4 {
+ font-size: 14pt; }
+ ul.blogTagCloud .tagCount3 {
+ font-size: 12pt; }
+ ul.blogTagCloud .tagCount2 {
+ font-size: 10pt; }
+ ul.blogTagCloud .tagCount1 {
+ font-size: 8pt; }
diff --git a/css/cms.css b/css/cms.css
index df0da49..7aa1caf 100755
--- a/css/cms.css
+++ b/css/cms.css
@@ -7,81 +7,66 @@
/*
* Sprite maps & Icons
*/
-.blog-icon-sprite, .gridfield-icon .blog-icon-timer {
- background-image: url('../images/blog-icon-s0a5ab5f851.png');
- background-repeat: no-repeat;
-}
-
-.gridfield-icon .blog-icon-timer {
- background-position: 0 0;
-}
+.gridfield-icon.blog-icon-timer {
+ background: url("../images/blog-icon/timer.png") center no-repeat; }
#FeaturedImage .middleColumn {
clear: none;
- float: left;
-}
+ float: left; }
-.blog-admin-sidebar {
+.has-panel .cms-content-tools.blog-admin-sidebar {
width: 280px;
border-right: none;
border-left: 1px solid #C0C0C2;
- position: absolute;
+ position: absolute !important;
+ /* overrides cms !imporant style */
right: 0px;
- bottom: 0px;
- height: 100%;
-}
-.blog-admin-sidebar .cms-panel-toggle a {
- text-align: left;
-}
-.blog-admin-sidebar ~ .blog-admin-outer {
- width: 100%;
- padding-right: 280px;
- position: absolute;
- height: 100%;
- overflow-y: hidden;
- overflow-x: hidden;
- box-sizing: border-box;
-}
-.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset {
- position: relative;
- overflow: auto;
- height: 100%;
- width: 100%;
-}
-.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title label {
- float: none;
-}
-.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title .middleColumn, .blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title input {
- width: 100%;
- max-width: 100%;
- margin-left: 0;
-}
-.blog-admin-sidebar .cms-content-view > .field + .field {
- margin-top: 10px;
-}
-.blog-admin-sidebar .cms-content-view > .field.urlsegment .preview {
- padding-top: 0;
- line-height: 25px;
-}
-.blog-admin-sidebar .cms-content-view > .field.urlsegment .edit {
- float: right;
-}
-.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .date {
- width: 60%;
-}
-.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .time {
- width: 36%;
- float: right;
-}
-.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn .middleColumn, .blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn input {
- width: 100%;
-}
-.blog-admin-sidebar.collapsed ~ .blog-admin-outer {
- padding-right: 41px;
-}
-.blog-admin-sidebar.cms-content-tools .cms-panel-content {
- width: auto;
-}
+ top: 0;
+ height: 100%; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle a {
+ text-align: left;
+ margin: 0; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-panel-toggle.south {
+ border-top: 1px solid #aaaaaa; }
+ .has-panel .cms-content-tools.blog-admin-sidebar ~ .blog-admin-outer {
+ width: 100%;
+ padding-right: 280px;
+ position: absolute;
+ height: 100%;
+ overflow-y: hidden;
+ overflow-x: hidden;
+ box-sizing: border-box; }
+ .has-panel .cms-content-tools.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset {
+ position: relative;
+ overflow: auto;
+ height: 100%;
+ width: 100%; }
+ .has-panel .cms-content-tools.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title label {
+ float: none; }
+ .has-panel .cms-content-tools.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title .middleColumn, .has-panel .cms-content-tools.blog-admin-sidebar ~ .blog-admin-outer > .ss-tabset #Title input {
+ width: 100%;
+ max-width: 100%;
+ margin-left: 0; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field + .field {
+ margin-top: 10px; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.urlsegment .preview {
+ padding-top: 0;
+ line-height: 25px; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.urlsegment .edit {
+ float: right; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .date {
+ width: 60%; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn > .time {
+ width: 36%;
+ float: right; }
+ .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn .middleColumn, .has-panel .cms-content-tools.blog-admin-sidebar .cms-content-view > .field.datetime > .middleColumn input {
+ width: 100%; }
+ .has-panel .cms-content-tools.blog-admin-sidebar.collapsed ~ .blog-admin-outer {
+ padding-right: 41px; }
+ .has-panel .cms-content-tools.blog-admin-sidebar.collapsed ~ .blog-admin-outer #Root_Main {
+ margin-right: 15px; }
+ .has-panel .cms-content-tools.blog-admin-sidebar.cms-content-tools .cms-panel-content {
+ width: auto; }
.toggle-description {
text-indent: -1000000px;
@@ -89,63 +74,59 @@
background: url("../images/information.png") no-repeat center center;
width: 20px;
height: 20px;
- margin-left: 4px;
-}
+ margin-left: 4px; }
.middleColumn.toggle-description-correct-middle {
margin-left: 0;
float: left;
- width: 416px;
-}
+ width: 416px; }
label.right.toggle-description-correct-right {
display: inline-block;
margin-left: 0;
clear: none;
- float: left;
-}
+ float: left; }
.description.toggle-description-correct-description {
width: 416px;
- padding: 12px 0;
-}
+ padding: 12px 0; }
.custom-summary .ui-accordion-content .field {
- margin: 0;
-}
+ margin: 0; }
+
.custom-summary .ui-accordion-content,
.custom-summary .ui-accordion-content .field {
- padding: 0;
-}
+ padding: 0; }
+
.custom-summary .ui-icon-triangle-1-e {
- background-position: -16px -128px;
-}
+ background-position: -16px -128px; }
.cms table.ss-gridfield-table tr td.MergeAction {
- width: 225px;
-}
-.cms table.ss-gridfield-table tr td.MergeAction a {
- display: block;
- height: 100%;
- width: 100%;
-}
-.cms table.ss-gridfield-table tr td.MergeAction select {
- width: 150px;
-}
+ width: 225px; }
+ .cms table.ss-gridfield-table tr td.MergeAction a {
+ display: block;
+ height: 100%;
+ width: 100%; }
+ .cms table.ss-gridfield-table tr td.MergeAction select {
+ width: 150px; }
.cms-content-actions,
.cms-preview-controls {
- z-index: 999;
-}
+ z-index: 999; }
.blog-cms-categorisation .MergeActionReveal {
- margin-left: 10px;
-}
+ margin-left: 10px; }
+
+.blog-cms-categorisation .toolbar--content {
+ margin-top: 0; }
+
.blog-cms-categorisation .MergeActionReveal:after {
content: '';
background: url("../images/move-icon.png");
display: inline-block;
height: 16px;
width: 16px;
- margin-left: 4px;
-}
+ margin-left: 4px; }
+
+.blog-cms-categorisation button.action {
+ margin-left: 5px; }
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..4aa2f74
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,17 @@
+var sass = require("gulp-sass");
+var gulp = require("gulp");
+var watch = require('gulp-watch');
+
+gulp.task("scss", function () {
+ gulp.src("./scss/*.scss")
+ .pipe(sass().on('error', sass.logError))
+ .pipe(gulp.dest("./css"));
+});
+
+gulp.task('watch', ['scss'], function() {
+ gulp.watch('./scss/*.scss', ['scss']);
+});
+
+gulp.task('default', ['scss'], function() {
+ // noop
+});
diff --git a/js/cms.js b/js/cms.js
index 6dbefdf..36fb506 100644
--- a/js/cms.js
+++ b/js/cms.js
@@ -113,6 +113,10 @@
if(!this.hasClass('collapsed') && ($(".blog-admin-outer").width() < this.getMinInnerWidth())) {
this.collapsePanel();
}
+
+ window.onresize = function() {
+ this.updateLayout();
+ }.bind(this);
},
togglePanel: function(bool, silent) {
this._super(bool, silent);
@@ -124,9 +128,16 @@
* @returns {undefined}
*/
updateLayout: function() {
+ $(this).css('height', '100%');
+ var currentHeight = $(this).outerHeight();
+ var bottomHeight = $('.cms-content-actions').eq(0).outerHeight();
+ $(this).css('height', (currentHeight - bottomHeight) + "px");
+ $(this).css('bottom', bottomHeight + "px");
+
$('.cms-container').updateLayoutOptions({
minContentWidth: 820 + this.width()
});
+
}
});
diff --git a/js/gridfieldaddbydbfield.js b/js/gridfieldaddbydbfield.js
index f6d31e2..67799f3 100644
--- a/js/gridfieldaddbydbfield.js
+++ b/js/gridfieldaddbydbfield.js
@@ -1,20 +1,16 @@
(function ($) {
-
$.entwine('ss', function ($) {
-
/**
* Prevent the CMS hijacking the return key
*/
$('.add-existing-autocompleter input.text').entwine({
'onkeydown': function (e) {
- if(e.which == 13) {
+ if (e.which == 13) {
$parent = $(this).parents('.add-existing-autocompleter');
$parent.find('button[type="submit"]').click();
return false;
}
}
});
-
});
-
})(jQuery);
diff --git a/lang/en.yml b/lang/en.yml
index 9ba7ddd..afffaf8 100755
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -87,7 +87,7 @@ en:
PLURALNAME: 'Blog Recent Posts Widgets'
SINGULARNAME: 'Blog Recent Posts Widget'
BlogTag:
- Duplicate: 'A blog tags already exists with that name'
+ Duplicate: 'A blog tag already exists with that name'
PLURALNAME: 'Blog Tags'
SINGULARNAME: 'Blog Tag'
Title: Title
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..4fe994b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "silverstripe-blog",
+ "version": "3.0.0",
+ "description": "Silverstripe blog module",
+ "main": "index.js",
+ "directories": {
+ "doc": "docs",
+ "test": "tests"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/silverstripe/silverstripe-blog.git"
+ },
+ "author": "",
+ "license": "BSD-3",
+ "bugs": {
+ "url": "https://github.com/silverstripe/silverstripe-blog/issues"
+ },
+ "homepage": "https://github.com/silverstripe/silverstripe-blog#readme",
+ "devDependencies": {
+ "gulp": "^3.9.1",
+ "gulp-sass": "^2.3.1",
+ "gulp-watch": "^4.3.6"
+ }
+}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..f7339cb
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,18 @@
+
@@ -327,7 +376,7 @@ class Blog extends Page implements PermissionProvider
}
$writerField = ListboxField::create('Writers', 'Writers', $members)
- ->setMultiple(true)
+ // ->setMultiple(true)
->setRightTitle('help')
->setDescription('
A writer has full control over creating, editing and publishing BlogPosts they have authored or have been assigned to. Writers are unable to edit BlogPosts to which they are not assigned.
@@ -343,7 +392,7 @@ class Blog extends Page implements PermissionProvider
}
$contributorField = ListboxField::create('Contributors', 'Contributors', $members)
- ->setMultiple(true)
+ // ->setMultiple(true)
->setRightTitle('help')
->setDescription('
Contributors have the ability to create or edit BlogPosts, but are unable to publish without authorisation of an editor. They are also unable to assign other contributing authors to any of their BlogPosts.
@@ -357,11 +406,14 @@ class Blog extends Page implements PermissionProvider
$contributorField = $contributorField->performDisabledTransformation();
}
- $fields->addFieldsToTab('Root.Users', array(
- $editorField,
- $writerField,
- $contributorField
- ));
+ $fields->addFieldsToTab(
+ 'Root.Users',
+ array(
+ $editorField,
+ $writerField,
+ $contributorField
+ )
+ );
return $fields;
}
@@ -471,7 +523,10 @@ class Blog extends Page implements PermissionProvider
$stage = '_' . $stage;
}
- $query->innerJoin('BlogPost', sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage));
+ $query->innerJoin(
+ DataObject::getSchema()->tableName(BlogPost::class),
+ sprintf('"SiteTree%s"."ID" = "BlogPost%s"."ID"', $stage, $stage)
+ );
$conn = DB::getConn();
@@ -517,7 +572,13 @@ class Blog extends Page implements PermissionProvider
*/
public function ProfileLink($urlSegment)
{
- return Controller::join_links($this->Link(), 'profile', $urlSegment);
+ $baseLink = $this->Link();
+ if ($baseLink === '/') {
+ // Handle homepage blogs
+ $baseLink = RootURLController::get_homepage_link();
+ }
+
+ return Controller::join_links($baseLink, 'profile', $urlSegment);
}
/**
@@ -608,13 +669,13 @@ class Blog extends Page implements PermissionProvider
return $group;
}
- $group = new Group();
+ $group = Group::create();
$group->Title = 'Blog users';
$group->Code = $code;
$group->write();
- $permission = new Permission();
+ $permission = Permission::create();
$permission->Code = $this->config()->grant_user_permission;
$group->Permissions()->add($permission);
@@ -622,510 +683,3 @@ class Blog extends Page implements PermissionProvider
return $group;
}
}
-
-/**
- * @package silverstripe
- * @subpackage blog
- */
-class Blog_Controller extends Page_Controller
-{
- /**
- * @var array
- */
- private static $allowed_actions = array(
- 'archive',
- 'tag',
- 'category',
- 'rss',
- 'profile',
- );
-
- /**
- * @var array
- */
- private static $url_handlers = array(
- 'tag/$Tag!/$Rss' => 'tag',
- 'category/$Category!/$Rss' => 'category',
- 'archive/$Year!/$Month/$Day' => 'archive',
- 'profile/$URLSegment!' => 'profile',
- );
-
- /**
- * @var array
- */
- private static $casting = array(
- 'MetaTitle' => 'Text',
- 'FilterDescription' => 'Text',
- );
-
- /**
- * The current Blog Post DataList query.
- *
- * @var DataList
- */
- protected $blogPosts;
-
- /**
- * @return string
- */
- public function index()
- {
- /**
- * @var Blog $dataRecord
- */
- $dataRecord = $this->dataRecord;
-
- $this->blogPosts = $dataRecord->getBlogPosts();
-
- return $this->render();
- }
-
- /**
- * Renders a Blog Member's profile.
- *
- * @return SS_HTTPResponse
- */
- public function profile()
- {
- $profile = $this->getCurrentProfile();
-
- if (!$profile) {
- return $this->httpError(404, 'Not Found');
- }
-
- $this->blogPosts = $this->getCurrentProfilePosts();
-
- return $this->render();
- }
-
- /**
- * Get the Member associated with the current URL segment.
- *
- * @return null|Member
- */
- public function getCurrentProfile()
- {
- $urlSegment = $this->request->param('URLSegment');
-
- if ($urlSegment) {
- return Member::get()
- ->filter('URLSegment', $urlSegment)
- ->first();
- }
-
- return null;
- }
-
- /**
- * Get posts related to the current Member profile.
- *
- * @return null|DataList
- */
- public function getCurrentProfilePosts()
- {
- $profile = $this->getCurrentProfile();
-
- if ($profile) {
- return $profile->BlogPosts()->filter('ParentID', $this->ID);
- }
-
- return null;
- }
-
- /**
- * Renders an archive for a specified date. This can be by year or year/month.
- *
- * @return null|SS_HTTPResponse
- */
- public function archive()
- {
- /**
- * @var Blog $dataRecord
- */
- $dataRecord = $this->dataRecord;
-
- $year = $this->getArchiveYear();
- $month = $this->getArchiveMonth();
- $day = $this->getArchiveDay();
-
- if ($this->request->param('Month') && !$month) {
- $this->httpError(404, 'Not Found');
- }
-
- if ($month && $this->request->param('Day') && !$day) {
- $this->httpError(404, 'Not Found');
- }
-
- if ($year) {
- $this->blogPosts = $dataRecord->getArchivedBlogPosts($year, $month, $day);
-
- return $this->render();
- }
-
- $this->httpError(404, 'Not Found');
-
- return null;
- }
-
- /**
- * Fetches the archive year from the url.
- *
- * @return int
- */
- public function getArchiveYear()
- {
- if ($this->request->param('Year')) {
- if (preg_match('/^[0-9]{4}$/', $year = $this->request->param('Year'))) {
- return (int) $year;
- }
- } elseif ($this->request->param('Action') == 'archive') {
- return SS_Datetime::now()->Year();
- }
-
- return null;
- }
-
- /**
- * Fetches the archive money from the url.
- *
- * @return null|int
- */
- public function getArchiveMonth()
- {
- $month = $this->request->param('Month');
-
- if (preg_match('/^[0-9]{1,2}$/', $month)) {
- if ($month > 0 && $month < 13) {
- if (checkdate($month, 01, $this->getArchiveYear())) {
- return (int) $month;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Fetches the archive day from the url.
- *
- * @return null|int
- */
- public function getArchiveDay()
- {
- $day = $this->request->param('Day');
-
- if (preg_match('/^[0-9]{1,2}$/', $day)) {
- if (checkdate($this->getArchiveMonth(), $day, $this->getArchiveYear())) {
- return (int) $day;
- }
- }
-
- return null;
- }
-
- /**
- * Renders the blog posts for a given tag.
- *
- * @return null|SS_HTTPResponse
- */
- public function tag()
- {
- $tag = $this->getCurrentTag();
-
- if ($tag) {
- $this->blogPosts = $tag->BlogPosts();
-
- if($this->isRSS()) {
- return $this->rssFeed($this->blogPosts, $tag->getLink());
- } else {
- return $this->render();
- }
- }
-
- $this->httpError(404, 'Not Found');
-
- return null;
- }
-
- /**
- * Tag Getter for use in templates.
- *
- * @return null|BlogTag
- */
- public function getCurrentTag()
- {
- /**
- * @var Blog $dataRecord
- */
- $dataRecord = $this->dataRecord;
- $tag = $this->request->param('Tag');
- if ($tag) {
- return $dataRecord->Tags()
- ->filter('URLSegment', array($tag, rawurlencode($tag)))
- ->first();
- }
- return null;
- }
-
- /**
- * Renders the blog posts for a given category.
- *
- * @return null|SS_HTTPResponse
- */
- public function category()
- {
- $category = $this->getCurrentCategory();
-
- if ($category) {
- $this->blogPosts = $category->BlogPosts();
-
- if($this->isRSS()) {
- return $this->rssFeed($this->blogPosts, $category->getLink());
- } else {
- return $this->render();
- }
- }
-
- $this->httpError(404, 'Not Found');
-
- return null;
- }
-
- /**
- * Category Getter for use in templates.
- *
- * @return null|BlogCategory
- */
- public function getCurrentCategory()
- {
- /**
- * @var Blog $dataRecord
- */
- $dataRecord = $this->dataRecord;
- $category = $this->request->param('Category');
- if ($category) {
- return $dataRecord->Categories()
- ->filter('URLSegment', array($category, rawurlencode($category)))
- ->first();
- }
- return null;
- }
-
- /**
- * Get the meta title for the current action.
- *
- * @return string
- */
- public function getMetaTitle()
- {
- $title = $this->data()->getTitle();
- $filter = $this->getFilterDescription();
-
- if ($filter) {
- $title = sprintf('%s - %s', $title, $filter);
- }
-
- $this->extend('updateMetaTitle', $title);
-
- return $title;
- }
-
- /**
- * Returns a description of the current filter.
- *
- * @return string
- */
- public function getFilterDescription()
- {
- $items = array();
-
- $list = $this->PaginatedList();
- $currentPage = $list->CurrentPage();
-
- if ($currentPage > 1) {
- $items[] = _t(
- 'Blog.FILTERDESCRIPTION_PAGE',
- 'Page {page}',
- null,
- array(
- 'page' => $currentPage,
- )
- );
- }
-
- if ($author = $this->getCurrentProfile()) {
- $items[] = _t(
- 'Blog.FILTERDESCRIPTION_AUTHOR',
- 'By {author}',
- null,
- array(
- 'author' => $author->Title,
- )
- );
- }
-
- if ($tag = $this->getCurrentTag()) {
- $items[] = _t(
- 'Blog.FILTERDESCRIPTION_TAG',
- 'Tagged with {tag}',
- null,
- array(
- 'tag' => $tag->Title,
- )
- );
- }
-
- if ($category = $this->getCurrentCategory()) {
- $items[] = _t(
- 'Blog.FILTERDESCRIPTION_CATEGORY',
- 'In category {category}',
- null,
- array(
- 'category' => $category->Title,
- )
- );
- }
-
- if ($this->owner->getArchiveYear()) {
- if ($this->owner->getArchiveDay()) {
- $date = $this->owner->getArchiveDate()->Nice();
- } elseif ($this->owner->getArchiveMonth()) {
- $date = $this->owner->getArchiveDate()->format('F, Y');
- } else {
- $date = $this->owner->getArchiveDate()->format('Y');
- }
-
- $items[] = _t(
- 'Blog.FILTERDESCRIPTION_DATE',
- 'In {date}',
- null,
- array(
- 'date' => $date,
- )
- );
- }
-
- $result = '';
-
- if ($items) {
- $result = implode(', ', $items);
- }
-
- $this->extend('updateFilterDescription', $result);
-
- return $result;
- }
-
- /**
- * Returns a list of paginated blog posts based on the BlogPost dataList.
- *
- * @return PaginatedList
- */
- public function PaginatedList()
- {
- $allPosts = $this->blogPosts ?: new ArrayList();
-
- $posts = new PaginatedList($allPosts);
-
- // Set appropriate page size
- if ($this->PostsPerPage > 0) {
- $pageSize = $this->PostsPerPage;
- } elseif ($count = $allPosts->count()) {
- $pageSize = $count;
- } else {
- $pageSize = 99999;
- }
- $posts->setPageLength($pageSize);
-
- // Set current page
- $start = $this->request->getVar($posts->getPaginationGetVar());
- $posts->setPageStart($start);
-
- return $posts;
- }
-
- /**
- * Displays an RSS feed of blog posts.
- *
- * @return string
- */
- public function rss()
- {
- /**
- * @var Blog $dataRecord
- */
- $dataRecord = $this->dataRecord;
-
- $this->blogPosts = $dataRecord->getBlogPosts();
-
- return $this->rssFeed($this->blogPosts, $this->Link());
- }
-
- /**
- * Returns the current archive date.
- *
- * @return null|Date
- */
- public function getArchiveDate()
- {
- $year = $this->getArchiveYear();
- $month = $this->getArchiveMonth();
- $day = $this->getArchiveDay();
-
- if ($year) {
- if ($month) {
- $date = sprintf('%s-%s-01', $year, $month);
-
- if ($day) {
- $date = sprintf('%s-%s-%s', $year, $month, $day);
- }
- } else {
- $date = sprintf('%s-01-01', $year);
- }
-
- return DBField::create_field('Date', $date);
- }
-
- return null;
- }
-
- /**
- * Returns a link to the RSS feed.
- *
- * @return string
- */
- public function getRSSLink()
- {
- return $this->Link('rss');
- }
-
- /**
- * Displays an RSS feed of the given blog posts.
- *
- * @param DataList $blogPosts
- * @param string $link
- *
- * @return string
- */
- protected function rssFeed($blogPosts, $link)
- {
- $rss = new RSSFeed($blogPosts, $link, $this->MetaTitle, $this->MetaDescription);
-
- $this->extend('updateRss', $rss);
-
- return $rss->outputToBrowser();
- }
-
- /**
- * Returns true if the $Rss sub-action for categories/tags has been set to "rss"
- */
- private function isRSS()
- {
- $rss = $this->request->param('Rss');
- if(is_string($rss) && strcasecmp($rss, "rss") == 0) {
- return true;
- } else {
- return false;
- }
- }
-}
diff --git a/src/Model/BlogCategory.php b/src/Model/BlogCategory.php
new file mode 100644
index 0000000..e527d71
--- /dev/null
+++ b/src/Model/BlogCategory.php
@@ -0,0 +1,79 @@
+ 'Varchar(255)',
+ 'URLSegment' => 'Varchar(255)'
+ );
+
+ /**
+ * @var array
+ */
+ private static $has_one = array(
+ 'Blog' => Blog::class,
+ );
+
+ /**
+ * @var array
+ */
+ private static $belongs_many_many = array(
+ 'BlogPosts' => BlogPost::class,
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getListUrlSegment()
+ {
+ return 'category';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getDuplicateError()
+ {
+ return _t('BlogCategory.Duplicate', 'A blog category already exists with that name.');
+ }
+}
diff --git a/code/extensions/BlogCommentExtension.php b/src/Model/BlogCommentExtension.php
similarity index 82%
rename from code/extensions/BlogCommentExtension.php
rename to src/Model/BlogCommentExtension.php
index de4576a..9768a60 100644
--- a/code/extensions/BlogCommentExtension.php
+++ b/src/Model/BlogCommentExtension.php
@@ -1,5 +1,10 @@
'tag',
+ 'category/$Category!/$Rss' => 'category',
+ 'archive/$Year!/$Month/$Day' => 'archive',
+ 'profile/$URLSegment!' => 'profile'
+ );
+
+ /**
+ * @var array
+ */
+ private static $casting = array(
+ 'MetaTitle' => 'Text',
+ 'FilterDescription' => 'Text'
+ );
+
+ /**
+ * The current Blog Post DataList query.
+ *
+ * @var DataList
+ */
+ protected $blogPosts;
+
+ /**
+ * @return string
+ */
+ public function index()
+ {
+ /**
+ * @var Blog $dataRecord
+ */
+ $dataRecord = $this->dataRecord;
+
+ $this->blogPosts = $dataRecord->getBlogPosts();
+
+ return $this->render();
+ }
+
+ /**
+ * Renders a Blog Member's profile.
+ *
+ * @return HTTPResponse
+ */
+ public function profile()
+ {
+ $profile = $this->getCurrentProfile();
+
+ if (!$profile) {
+ return $this->httpError(404, 'Not Found');
+ }
+
+ $this->blogPosts = $this->getCurrentProfilePosts();
+
+ return $this->render();
+ }
+
+ /**
+ * Get the Member associated with the current URL segment.
+ *
+ * @return null|Member
+ */
+ public function getCurrentProfile()
+ {
+ $urlSegment = $this->request->param('URLSegment');
+
+ if ($urlSegment) {
+ return Member::get()
+ ->filter('URLSegment', $urlSegment)
+ ->first();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get posts related to the current Member profile.
+ *
+ * @return null|DataList
+ */
+ public function getCurrentProfilePosts()
+ {
+ $profile = $this->getCurrentProfile();
+
+ if ($profile) {
+ return $profile->BlogPosts()->filter('ParentID', $this->ID);
+ }
+
+ return null;
+ }
+
+ /**
+ * Renders an archive for a specified date. This can be by year or year/month.
+ *
+ * @return null|HTTPResponse
+ */
+ public function archive()
+ {
+ /**
+ * @var Blog $dataRecord
+ */
+ $dataRecord = $this->dataRecord;
+
+ $year = $this->getArchiveYear();
+ $month = $this->getArchiveMonth();
+ $day = $this->getArchiveDay();
+
+ if ($this->request->param('Month') && !$month) {
+ $this->httpError(404, 'Not Found');
+ }
+
+ if ($month && $this->request->param('Day') && !$day) {
+ $this->httpError(404, 'Not Found');
+ }
+
+ if ($year) {
+ $this->blogPosts = $dataRecord->getArchivedBlogPosts($year, $month, $day);
+
+ return $this->render();
+ }
+
+ $this->httpError(404, 'Not Found');
+
+ return null;
+ }
+
+ /**
+ * Fetches the archive year from the url.
+ *
+ * @return int
+ */
+ public function getArchiveYear()
+ {
+ if ($this->request->param('Year')) {
+ if (preg_match('/^[0-9]{4}$/', $year = $this->request->param('Year'))) {
+ return (int) $year;
+ }
+ } elseif ($this->request->param('Action') == 'archive') {
+ return DBDatetime::now()->Year();
+ }
+
+ return null;
+ }
+
+ /**
+ * Fetches the archive money from the url.
+ *
+ * @return null|int
+ */
+ public function getArchiveMonth()
+ {
+ $month = $this->request->param('Month');
+
+ if (preg_match('/^[0-9]{1,2}$/', $month)) {
+ if ($month > 0 && $month < 13) {
+ if (checkdate($month, 01, $this->getArchiveYear())) {
+ return (int) $month;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Fetches the archive day from the url.
+ *
+ * @return null|int
+ */
+ public function getArchiveDay()
+ {
+ $day = $this->request->param('Day');
+
+ if (preg_match('/^[0-9]{1,2}$/', $day)) {
+ if (checkdate($this->getArchiveMonth(), $day, $this->getArchiveYear())) {
+ return (int) $day;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Renders the blog posts for a given tag.
+ *
+ * @return null|HTTPResponse
+ */
+ public function tag()
+ {
+ $tag = $this->getCurrentTag();
+
+ if ($tag) {
+ $this->blogPosts = $tag->BlogPosts();
+
+ if($this->isRSS()) {
+ return $this->rssFeed($this->blogPosts, $tag->getLink());
+ } else {
+ return $this->render();
+ }
+ }
+
+ $this->httpError(404, 'Not Found');
+
+ return null;
+ }
+
+ /**
+ * Tag Getter for use in templates.
+ *
+ * @return null|BlogTag
+ */
+ public function getCurrentTag()
+ {
+ /**
+ * @var Blog $dataRecord
+ */
+ $dataRecord = $this->dataRecord;
+ $tag = $this->request->param('Tag');
+ if ($tag) {
+ return $dataRecord->Tags()
+ ->filter('URLSegment', array($tag, rawurlencode($tag)))
+ ->first();
+ }
+ return null;
+ }
+
+ /**
+ * Renders the blog posts for a given category.
+ *
+ * @return null|HTTPResponse
+ */
+ public function category()
+ {
+ $category = $this->getCurrentCategory();
+
+ if ($category) {
+ $this->blogPosts = $category->BlogPosts();
+
+ if($this->isRSS()) {
+ return $this->rssFeed($this->blogPosts, $category->getLink());
+ } else {
+ return $this->render();
+ }
+ }
+
+ $this->httpError(404, 'Not Found');
+
+ return null;
+ }
+
+ /**
+ * Category Getter for use in templates.
+ *
+ * @return null|BlogCategory
+ */
+ public function getCurrentCategory()
+ {
+ /**
+ * @var Blog $dataRecord
+ */
+ $dataRecord = $this->dataRecord;
+ $category = $this->request->param('Category');
+ if ($category) {
+ return $dataRecord->Categories()
+ ->filter('URLSegment', array($category, rawurlencode($category)))
+ ->first();
+ }
+ return null;
+ }
+
+ /**
+ * Get the meta title for the current action.
+ *
+ * @return string
+ */
+ public function getMetaTitle()
+ {
+ $title = $this->data()->getTitle();
+ $filter = $this->getFilterDescription();
+
+ if ($filter) {
+ $title = sprintf('%s - %s', $title, $filter);
+ }
+
+ $this->extend('updateMetaTitle', $title);
+
+ return $title;
+ }
+
+ /**
+ * Returns a description of the current filter.
+ *
+ * @return string
+ */
+ public function getFilterDescription()
+ {
+ $items = array();
+
+ $list = $this->PaginatedList();
+ $currentPage = $list->CurrentPage();
+
+ if ($currentPage > 1) {
+ $items[] = _t(
+ 'Blog.FILTERDESCRIPTION_PAGE',
+ 'Page {page}',
+ null,
+ array(
+ 'page' => $currentPage
+ )
+ );
+ }
+
+ if ($author = $this->getCurrentProfile()) {
+ $items[] = _t(
+ 'Blog.FILTERDESCRIPTION_AUTHOR',
+ 'By {author}',
+ null,
+ array(
+ 'author' => $author->Title
+ )
+ );
+ }
+
+ if ($tag = $this->getCurrentTag()) {
+ $items[] = _t(
+ 'Blog.FILTERDESCRIPTION_TAG',
+ 'Tagged with {tag}',
+ null,
+ array(
+ 'tag' => $tag->Title
+ )
+ );
+ }
+
+ if ($category = $this->getCurrentCategory()) {
+ $items[] = _t(
+ 'Blog.FILTERDESCRIPTION_CATEGORY',
+ 'In category {category}',
+ null,
+ array(
+ 'category' => $category->Title
+ )
+ );
+ }
+
+ if ($this->owner->getArchiveYear()) {
+ if ($this->owner->getArchiveDay()) {
+ $date = $this->owner->getArchiveDate()->Nice();
+ } elseif ($this->owner->getArchiveMonth()) {
+ $date = $this->owner->getArchiveDate()->format('F, Y');
+ } else {
+ $date = $this->owner->getArchiveDate()->format('Y');
+ }
+
+ $items[] = _t(
+ 'Blog.FILTERDESCRIPTION_DATE',
+ 'In {date}',
+ null,
+ array(
+ 'date' => $date,
+ )
+ );
+ }
+
+ $result = '';
+
+ if ($items) {
+ $result = implode(', ', $items);
+ }
+
+ $this->extend('updateFilterDescription', $result);
+
+ return $result;
+ }
+
+ /**
+ * Returns a list of paginated blog posts based on the BlogPost dataList.
+ *
+ * @return PaginatedList
+ */
+ public function PaginatedList()
+ {
+ $allPosts = $this->blogPosts ?: ArrayList::create();
+ $posts = PaginatedList::create($allPosts);
+
+ // Set appropriate page size
+ if ($this->PostsPerPage > 0) {
+ $pageSize = $this->PostsPerPage;
+ } elseif ($count = $allPosts->count()) {
+ $pageSize = $count;
+ } else {
+ $pageSize = 99999;
+ }
+ $posts->setPageLength($pageSize);
+
+ // Set current page
+ $start = $this->request->getVar($posts->getPaginationGetVar());
+ $posts->setPageStart($start);
+
+ return $posts;
+ }
+
+ /**
+ * Displays an RSS feed of blog posts.
+ *
+ * @return string
+ */
+ public function rss()
+ {
+ /**
+ * @var Blog $dataRecord
+ */
+ $dataRecord = $this->dataRecord;
+
+ $this->blogPosts = $dataRecord->getBlogPosts();
+
+ return $this->rssFeed($this->blogPosts, $this->Link());
+ }
+
+ /**
+ * Returns the current archive date.
+ *
+ * @return null|Date
+ */
+ public function getArchiveDate()
+ {
+ $year = $this->getArchiveYear();
+ $month = $this->getArchiveMonth();
+ $day = $this->getArchiveDay();
+
+ if ($year) {
+ if ($month) {
+ $date = sprintf('%s-%s-01', $year, $month);
+
+ if ($day) {
+ $date = sprintf('%s-%s-%s', $year, $month, $day);
+ }
+ } else {
+ $date = sprintf('%s-01-01', $year);
+ }
+
+ $obj = DBDatetime::create('date');
+ $obj->setValue($date);
+ return $obj;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a link to the RSS feed.
+ *
+ * @return string
+ */
+ public function getRSSLink()
+ {
+ return $this->Link('rss');
+ }
+
+ /**
+ * Displays an RSS feed of the given blog posts.
+ *
+ * @param DataList $blogPosts
+ * @param string $link
+ *
+ * @return string
+ */
+ protected function rssFeed($blogPosts, $link)
+ {
+ $rss = new RSSFeed($blogPosts, $link, $this->MetaTitle, $this->MetaDescription);
+
+ $this->extend('updateRss', $rss);
+
+ return $rss->outputToBrowser();
+ }
+
+ /**
+ * Returns true if the $Rss sub-action for categories/tags has been set to "rss"
+ *
+ * @return bool
+ */
+ protected function isRSS()
+ {
+ $rss = $this->request->param('Rss');
+ return (is_string($rss) && strcasecmp($rss, 'rss') == 0);
+ }
+}
diff --git a/code/extensions/BlogFilter.php b/src/Model/BlogFilter.php
similarity index 63%
rename from code/extensions/BlogFilter.php
rename to src/Model/BlogFilter.php
index 65dc027..da53fc3 100644
--- a/code/extensions/BlogFilter.php
+++ b/src/Model/BlogFilter.php
@@ -1,5 +1,20 @@
shouldFilter() && $this->subclassForBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
- $stage = Versioned::current_stage();
+ $stage = Versioned::get_stage();
if ($stage == 'Stage') {
$stage = '';
@@ -26,8 +41,11 @@ class BlogFilter extends Lumberjack
}
$dataQuery = $staged->dataQuery()
- ->innerJoin('BlogPost', sprintf('"BlogPost%s"."ID" = "SiteTree%s"."ID"', $stage, $stage))
- ->where(sprintf('"PublishDate" < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
+ ->innerJoin(
+ DataObject::getSchema()->tableName(BlogPost::class),
+ sprintf('"BlogPost%s"."ID" = "SiteTree%s"."ID"', $stage, $stage)
+ )
+ ->where(sprintf('"PublishDate" < \'%s\'', Convert::raw2sql(DBDatetime::now())));
$staged = $staged->setDataQuery($dataQuery);
}
@@ -40,7 +58,7 @@ class BlogFilter extends Lumberjack
*/
protected function subclassForBlog()
{
- return in_array(get_class($this->owner), ClassInfo::subClassesFor('Blog'));
+ return in_array(get_class($this->owner), ClassInfo::subclassesFor(Blog::class));
}
/**
@@ -52,8 +70,11 @@ class BlogFilter extends Lumberjack
if (!$this->shouldFilter() && $this->isBlog() && !Permission::check('VIEW_DRAFT_CONTENT')) {
$dataQuery = $staged->dataQuery()
- ->innerJoin('BlogPost', '"BlogPost_Live"."ID" = "SiteTree_Live"."ID"')
- ->where(sprintf('"PublishDate" < \'%s\'', Convert::raw2sql(SS_Datetime::now())));
+ ->innerJoin(
+ DataObject::getSchema()->tableName(BlogPost::class),
+ '"BlogPost_Live"."ID" = "SiteTree_Live"."ID"'
+ )
+ ->where(sprintf('"PublishDate" < \'%s\'', Convert::raw2sql(DBDatetime::now())));
$staged = $staged->setDataQuery($dataQuery);
}
@@ -82,33 +103,16 @@ class BlogFilter extends Lumberjack
'ClassName' => $excluded
));
- $gridField = new BlogFilter_GridField(
+ $gridField = BlogFilterGridField::create(
'ChildPages',
$this->getLumberjackTitle(),
$pages,
$this->getLumberjackGridFieldConfig()
);
- $tab = new Tab('ChildPages', $this->getLumberjackTitle(), $gridField);
+ $tab = Tab::create('ChildPages', $this->getLumberjackTitle(), $gridField);
$fields->insertBefore($tab, 'Main');
}
}
}
-
-
-/**
- * Enables children of non-editable pages to be edited.
- */
-class BlogFilter_GridField extends GridField
-{
- /**
- * @param FormTransformation $transformation
- *
- * @return $this
- */
- public function transform(FormTransformation $transformation)
- {
- return $this;
- }
-}
diff --git a/src/Model/BlogFilter/BlogFilterGridField.php b/src/Model/BlogFilter/BlogFilterGridField.php
new file mode 100644
index 0000000..190ee1d
--- /dev/null
+++ b/src/Model/BlogFilter/BlogFilterGridField.php
@@ -0,0 +1,22 @@
+ 'Varchar',
- 'BlogProfileSummary' => 'Text',
+ 'URLSegment' => 'Varchar',
+ 'BlogProfileSummary' => 'Text'
);
/**
* @var array
*/
private static $has_one = array(
- 'BlogProfileImage' => 'Image',
+ 'BlogProfileImage' => Image::class
);
/**
* @var array
*/
private static $belongs_many_many = array(
- 'BlogPosts' => 'BlogPost',
+ 'BlogPosts' => BlogPost::class
);
/**
@@ -80,7 +93,6 @@ class BlogMemberExtension extends DataExtension
return $conflict->count() == 0;
}
-
/**
* {@inheritdoc}
*/
@@ -97,13 +109,13 @@ class BlogMemberExtension extends DataExtension
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
- $tab = new Tab('BlogPosts', 'Blog Posts');
+ $tab = Tab::create('BlogPosts', 'Blog Posts');
- $gridField = new GridField(
+ $gridField = GridField::create(
'BlogPosts',
'Blog Posts',
$this->owner->BlogPosts(),
- new GridFieldConfig_BlogPost()
+ GridFieldConfig_BlogPost::create()
);
$tab->Fields()->add($gridField);
diff --git a/src/Model/BlogObject.php b/src/Model/BlogObject.php
new file mode 100644
index 0000000..fd8bded
--- /dev/null
+++ b/src/Model/BlogObject.php
@@ -0,0 +1,246 @@
+extend('updateGetBlogPosts', $blogPosts);
+
+ return $blogPosts;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCMSFields()
+ {
+ $fields = TabSet::create(
+ 'Root',
+ Tab::create(
+ 'Main',
+ TextField::create('Title', _t(self::class . '.Title', 'Title'))
+ )
+ );
+
+ $fields = FieldList::create($fields);
+ $this->extend('updateCMSFields', $fields);
+
+ return $fields;
+ }
+
+ /**
+ * {@inheritdoc}
+ * @return ValidationResult
+ */
+ public function validate()
+ {
+ /** @var ValidationResult $validation */
+ $validation = parent::validate();
+ if (!$validation->isValid()) {
+ return $validation;
+ }
+
+ $blog = $this->Blog();
+ if (!$blog || !$blog->exists()) {
+ return $validation;
+ }
+
+ if ($this->getDuplicatesByField('Title')->count() > 0) {
+ $validation->addError($this->getDuplicateError(), self::DUPLICATE_EXCEPTION);
+ }
+
+ return $validation;
+ }
+
+ /**
+ * Returns a relative link to this category.
+ *
+ * @return string
+ */
+ public function getLink()
+ {
+ return Controller::join_links(
+ $this->Blog()->Link(),
+ $this->getListUrlSegment(),
+ $this->URLSegment
+ );
+ }
+
+ /**
+ * Inherits from the parent blog or can be overwritten using a DataExtension.
+ *
+ * @param null|Member $member
+ *
+ * @return bool
+ */
+ public function canView($member = null)
+ {
+ $extended = $this->extendedCan(__FUNCTION__, $member);
+
+ if ($extended !== null) {
+ return $extended;
+ }
+
+ return $this->Blog()->canView($member);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function canCreate($member = null, $context = array())
+ {
+ $extended = $this->extendedCan(__FUNCTION__, $member);
+
+ if ($extended !== null) {
+ return $extended;
+ }
+
+ $permission = Blog::config()->grant_user_permission;
+
+ return Permission::checkMember($member, $permission);
+ }
+
+ /**
+ * Inherits from the parent blog or can be overwritten using a DataExtension.
+ *
+ * @param null|Member $member
+ *
+ * @return bool
+ */
+ public function canDelete($member = null)
+ {
+ $extended = $this->extendedCan(__FUNCTION__, $member);
+
+ if ($extended !== null) {
+ return $extended;
+ }
+
+ return $this->Blog()->canDelete($member);
+ }
+
+ /**
+ * Inherits from the parent blog or can be overwritten using a DataExtension.
+ *
+ * @param null|Member $member
+ *
+ * @return bool
+ */
+ public function canEdit($member = null)
+ {
+ $extended = $this->extendedCan(__FUNCTION__, $member);
+
+ if ($extended !== null) {
+ return $extended;
+ }
+
+ return $this->Blog()->canEdit($member);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function onBeforeWrite()
+ {
+ parent::onBeforeWrite();
+ if ($this->exists() || empty($this->URLSegment)) {
+ return $this->generateURLSegment();
+ }
+ }
+
+ /**
+ * Generates a unique URLSegment from the title.
+ *
+ * @param int $increment
+ *
+ * @return string
+ */
+ public function generateURLSegment($increment = 0)
+ {
+ $increment = (int) $increment;
+ $filter = URLSegmentFilter::create();
+
+ // Setting this to on. Because of the UI flow, it would be quite a lot of work
+ // to support turning this off. (ie. the add by title flow would not work).
+ // If this becomes a problem we can approach it then.
+ // @see https://github.com/silverstripe/silverstripe-blog/issues/376
+ $filter->setAllowMultibyte(true);
+
+ $this->URLSegment = $filter->filter($this->Title);
+
+ if ($increment > 0) {
+ $this->URLSegment .= '-' . $increment;
+ }
+
+ if ($this->getDuplicatesByField('URLSegment')->count() > 0) {
+ $this->generateURLSegment($increment + 1);
+ }
+
+ return $this->URLSegment;
+ }
+
+ /**
+ * Looks for objects o the same type and the same value by the given Field
+ *
+ * @param string $field E.g. URLSegment or Title
+ * @return DataList
+ */
+ protected function getDuplicatesByField($field)
+ {
+ $duplicates = DataList::create(self::class)
+ ->filter(
+ [
+ $field => $this->$field,
+ 'BlogID' => (int) $this->BlogID
+ ]
+ );
+
+ if ($this->ID) {
+ $duplicates = $duplicates->exclude('ID', $this->ID);
+ }
+
+ return $duplicates;
+ }
+
+ /**
+ * This returns the url segment for the listing page.
+ * eg. 'categories' in /my-blog/categories/category-url
+ *
+ * This is not editable at the moment, but a method is being used incase we want
+ * to make it editable in the future. We can use this method to provide logic
+ * without replacing multiple areas of the code base. We're also not being opinionated
+ * about how the segment should be obtained at the moment and allowing for the
+ * implementation to decide.
+ *
+ * @return string
+ */
+ abstract protected function getListUrlSegment();
+
+ /**
+ * Returns an error message for this object when it tries to write a duplicate.
+ *
+ * @return string
+ */
+ abstract protected function getDuplicateError();
+}
diff --git a/code/model/BlogPost.php b/src/Model/BlogPost.php
similarity index 81%
rename from code/model/BlogPost.php
rename to src/Model/BlogPost.php
index 7e6ac15..ace1085 100644
--- a/code/model/BlogPost.php
+++ b/src/Model/BlogPost.php
@@ -1,5 +1,31 @@
'SS_Datetime',
+ 'PublishDate' => 'Datetime',
'AuthorNames' => 'Varchar(1024)',
- 'Summary' => 'HTMLText',
+ 'Summary' => 'HTMLText'
);
/**
* @var array
*/
private static $has_one = array(
- 'FeaturedImage' => 'Image',
+ 'FeaturedImage' => Image::class
);
/**
* @var array
*/
private static $many_many = array(
- 'Categories' => 'BlogCategory',
- 'Tags' => 'BlogTag',
- 'Authors' => 'Member',
+ 'Categories' => BlogCategory::class,
+ 'Tags' => BlogTag::class,
+ 'Authors' => Member::class
);
/**
* @var array
*/
private static $defaults = array(
- 'ShowInMenus' => false,
- 'InheritSideBar' => true,
- 'ProvideComments' => true,
+ 'ShowInMenus' => false,
+ 'InheritSideBar' => true,
+ 'ProvideComments' => true
);
/**
* @var array
*/
private static $extensions = array(
- 'BlogPostFilter',
+ BlogPostFilter::class
);
/**
* @var array
*/
private static $searchable_fields = array(
- 'Title',
+ 'Title'
);
/**
* @var array
*/
private static $summary_fields = array(
- 'Title',
+ 'Title'
);
/**
@@ -84,7 +116,7 @@ class BlogPost extends Page
*/
private static $casting = array(
'Excerpt' => 'HTMLText',
- 'Date' => 'SS_Datetime',
+ 'Date' => 'DBDatetime'
);
/**
@@ -174,9 +206,7 @@ class BlogPost extends Page
Requirements::css(BLOGGER_DIR . '/css/cms.css');
Requirements::javascript(BLOGGER_DIR . '/js/cms.js');
- $self =& $this;
-
- $this->beforeUpdateCMSFields(function ($fields) use ($self) {
+ $this->beforeUpdateCMSFields(function ($fields) {
$uploadField = UploadField::create('FeaturedImage', _t('BlogPost.FeaturedImage', 'Featured Image'));
$uploadField->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));
@@ -204,10 +234,8 @@ class BlogPost extends Page
$fields->insertAfter($summaryHolder, 'FeaturedImage');
- $fields->push(HiddenField::create('MenuTitle'));
-
$urlSegment = $fields->dataFieldByName('URLSegment');
- $urlSegment->setURLPrefix($self->Parent()->RelativeLink());
+ $urlSegment->setURLPrefix($this->Parent()->RelativeLink());
$fields->removeFieldsFromTab('Root.Main', array(
'MenuTitle',
@@ -217,35 +245,39 @@ class BlogPost extends Page
$authorField = ListboxField::create(
'Authors',
_t('BlogPost.Authors', 'Authors'),
- $self->getCandidateAuthors()->map()->toArray()
- )->setMultiple(true);
+ $this->getCandidateAuthors()->map()->toArray()
+ );
$authorNames = TextField::create(
'AuthorNames',
_t('BlogPost.AdditionalCredits', 'Additional Credits'),
null,
1024
- )->setDescription(_t(
+ )->setDescription(
+ _t(
'BlogPost.AdditionalCredits_Description',
- 'If some authors of this post don\'t have CMS access, enter their name(s) here. You can separate multiple names with a comma.')
+ 'If some authors of this post don\'t have CMS access, enter their name(s) here. You can separate multiple names with a comma.'
+ )
);
- if (!$self->canEditAuthors()) {
+ if (!$this->canEditAuthors()) {
$authorField = $authorField->performDisabledTransformation();
$authorNames = $authorNames->performDisabledTransformation();
}
$publishDate = DatetimeField::create('PublishDate', _t('BlogPost.PublishDate', 'Publish Date'));
$publishDate->getDateField()->setConfig('showcalendar', true);
- if (!$self->PublishDate) {
- $publishDate->setDescription(_t(
+ if (!$this->PublishDate) {
+ $publishDate->setDescription(
+ _t(
'BlogPost.PublishDate_Description',
- 'Will be set to "now" if published without a value.')
+ 'Will be set to "now" if published without a value.'
+ )
);
}
// Get categories and tags
- $parent = $self->Parent();
+ $parent = $this->Parent();
$categories = $parent instanceof Blog
? $parent->Categories()
: BlogCategory::get();
@@ -253,32 +285,36 @@ class BlogPost extends Page
? $parent->Tags()
: BlogTag::get();
- $options = BlogAdminSidebar::create(
- $publishDate,
- $urlSegment,
- TagField::create(
- 'Categories',
- _t('BlogPost.Categories', 'Categories'),
- $categories,
- $self->Categories()
- )
- ->setCanCreate($self->canCreateCategories())
- ->setShouldLazyLoad(true),
- TagField::create(
- 'Tags',
- _t('BlogPost.Tags', 'Tags'),
- $tags,
- $self->Tags()
- )
- ->setCanCreate($self->canCreateTags())
- ->setShouldLazyLoad(true),
- $authorField,
- $authorNames
- )->setTitle('Post Options');
-
- $options->setName('blog-admin-sidebar');
-
- $fields->insertBefore($options, 'Root');
+ // @todo: Reimplement the sidebar
+ // $options = BlogAdminSidebar::create(
+ $fields->addFieldsToTab(
+ 'Root.PostOptions',
+ [
+ $publishDate,
+ $urlSegment,
+ TagField::create(
+ 'Categories',
+ _t('BlogPost.Categories', 'Categories'),
+ $categories,
+ $this->Categories()
+ )
+ ->setCanCreate($this->canCreateCategories())
+ ->setShouldLazyLoad(true),
+ TagField::create(
+ 'Tags',
+ _t('BlogPost.Tags', 'Tags'),
+ $tags,
+ $this->Tags()
+ )
+ ->setCanCreate($this->canCreateTags())
+ ->setShouldLazyLoad(true),
+ $authorField,
+ $authorNames
+ ]
+ );
+ // )->setTitle('Post Options');
+ // $options->setName('blog-admin-sidebar');
+ // $fields->insertBefore($options, 'Root');
});
$fields = parent::getCMSFields();
@@ -297,11 +333,11 @@ class BlogPost extends Page
{
if ($this->config()->restrict_authors_to_group) {
return Group::get()->filter('Code', $this->config()->restrict_authors_to_group)->first()->Members();
- } else {
- $list = Member::get();
- $this->extend('updateCandidateAuthors', $list);
- return $list;
}
+
+ $list = Member::get();
+ $this->extend('updateCandidateAuthors', $list);
+ return $list;
}
/**
@@ -414,12 +450,12 @@ class BlogPost extends Page
public function onBeforePublish()
{
/**
- * @var SS_Datetime $publishDate
+ * @var DBDatetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
if (!$publishDate->getValue()) {
- $this->PublishDate = SS_Datetime::now()->getValue();
+ $this->PublishDate = DBDatetime::now()->getValue();
$this->write();
}
}
@@ -461,15 +497,15 @@ class BlogPost extends Page
return false;
}
- if($this->canEdit($member)) {
+ if ($this->canEdit($member)) {
return true;
}
/**
- * @var SS_Datetime $publishDate
+ * @var DBDatetime $publishDate
*/
$publishDate = $this->dbObject('PublishDate');
- if(!$publishDate->exists()) {
+ if (!$publishDate->exists()) {
return false;
}
@@ -565,7 +601,7 @@ class BlogPost extends Page
public function getMonthlyArchiveLink($type = 'day')
{
/**
- * @var SS_Datetime $date
+ * @var DBDatetime $date
*/
$date = $this->dbObject('PublishDate');
@@ -593,7 +629,7 @@ class BlogPost extends Page
public function getYearlyArchiveLink()
{
/**
- * @var SS_Datetime $date
+ * @var DBDatetime $date
*/
$date = $this->dbObject('PublishDate');
@@ -607,7 +643,7 @@ class BlogPost extends Page
*/
public function getCredits()
{
- $list = new ArrayList();
+ $list = ArrayList::create();
$list->merge($this->getDynamicCredits());
$list->merge($this->getStaticCredits());
@@ -708,11 +744,3 @@ class BlogPost extends Page
}
}
}
-
-/**
- * @package silverstripe
- * @subpackage blog
- */
-class BlogPost_Controller extends Page_Controller
-{
-}
diff --git a/src/Model/BlogPostController.php b/src/Model/BlogPostController.php
new file mode 100644
index 0000000..2b09699
--- /dev/null
+++ b/src/Model/BlogPostController.php
@@ -0,0 +1,14 @@
+addWhere(sprintf(
+ '"PublishDate" < \'%s\'',
+ Convert::raw2sql(DBDatetime::now())
+ ));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * This is a fix so that when we try to fetch subclasses of BlogPost, lazy loading includes the
+ * BlogPost table in its query. Leaving this table out means the default sort order column
+ * PublishDate causes an error.
+ *
+ * @see https://github.com/silverstripe/silverstripe-framework/issues/1682
+ *
+ * @param SQLSelect $query
+ * @param DataQuery $dataQuery
+ * @param DataObject $dataObject
+ */
+ public function augmentLoadLazyFields(SQLSelect &$query, DataQuery &$dataQuery = null, $dataObject)
+ {
+ $dataQuery->innerJoin(
+ DataObject::getSchema()->tableName(BlogPost::class),
+ '"SiteTree"."ID" = "BlogPost"."ID"'
+ );
+ }
+}
diff --git a/code/extensions/BlogPostNotifications.php b/src/Model/BlogPostNotifications.php
similarity index 91%
rename from code/extensions/BlogPostNotifications.php
rename to src/Model/BlogPostNotifications.php
index e3d7ca2..733c338 100644
--- a/code/extensions/BlogPostNotifications.php
+++ b/src/Model/BlogPostNotifications.php
@@ -1,5 +1,9 @@
'Varchar(255)',
+ 'URLSegment' => 'Varchar(255)'
+ );
+
+ /**
+ * @var array
+ */
+ private static $has_one = array(
+ 'Blog' => Blog::class
+ );
+
+ /**
+ * @var array
+ */
+ private static $belongs_many_many = array(
+ 'BlogPosts' => BlogPost::class
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getListUrlSegment()
+ {
+ return 'tag';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getDuplicateError()
+ {
+ return _t('BlogTag.Duplicate', 'A blog tag already exists with that name.');
+ }
+}
diff --git a/code/model/CategorisationObject.php b/src/Model/CategorisationObject.php
similarity index 69%
rename from code/model/CategorisationObject.php
rename to src/Model/CategorisationObject.php
index 811419e..827035b 100644
--- a/code/model/CategorisationObject.php
+++ b/src/Model/CategorisationObject.php
@@ -1,8 +1,11 @@
'Blog',
+ 'Blog' => Blog::class,
);
/**
@@ -54,13 +62,11 @@ class BlogArchiveWidget extends Widget
*/
public function getCMSFields()
{
- $self =& $this;
-
- $this->beforeUpdateCMSFields(function ($fields) use ($self) {
+ $this->beforeUpdateCMSFields(function ($fields) {
/**
* @var Enum $archiveType
*/
- $archiveType = $self->dbObject('ArchiveType');
+ $archiveType = $this->dbObject('ArchiveType');
$type = $archiveType->enumValues();
@@ -72,7 +78,11 @@ class BlogArchiveWidget extends Widget
* @var FieldList $fields
*/
$fields->merge(array(
- DropdownField::create('BlogID', _t('BlogArchiveWidget.Blog', 'Blog'), Blog::get()->map()),
+ DropdownField::create(
+ 'BlogID',
+ _t('BlogArchiveWidget.Blog', 'Blog'),
+ Blog::get()->map()
+ ),
DropdownField::create('ArchiveType', _t('BlogArchiveWidget.ArchiveType', 'ArchiveType'), $type),
NumericField::create('NumberToDisplay', _t('BlogArchiveWidget.NumberToDisplay', 'No. to Display'))
));
@@ -132,7 +142,3 @@ class BlogArchiveWidget extends Widget
return $archive;
}
}
-
-class BlogArchiveWidget_Controller extends Widget_Controller
-{
-}
diff --git a/src/Widgets/BlogArchiveWidgetController.php b/src/Widgets/BlogArchiveWidgetController.php
new file mode 100644
index 0000000..5e01105
--- /dev/null
+++ b/src/Widgets/BlogArchiveWidgetController.php
@@ -0,0 +1,14 @@
+ 'Int',
+ 'Order' => 'Varchar',
+ 'Direction' => 'Varchar',
+ );
+
+ /**
+ * @var array
+ */
+ private static $has_one = array(
+ 'Blog' => Blog::class,
+ );
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCMSFields()
+ {
+ $this->beforeUpdateCMSFields(function (FieldList $fields) {
+ $fields[] = DropdownField::create(
+ 'BlogID',
+ _t('BlogCategoriesWidget.Blog', 'Blog'),
+ Blog::get()->map()
+ );
+
+ $fields[] = NumericField::create(
+ 'Limit',
+ _t('BlogCategoriesWidget.Limit.Label', 'Limit'),
+ 0
+ )
+ ->setDescription(
+ _t(
+ 'BlogCategoriesWidget.Limit.Description',
+ 'Limit the number of categories shown by this widget (set to 0 to show all categories).'
+ )
+ )
+ ->setMaxLength(3);
+
+ $fields[] = DropdownField::create(
+ 'Order',
+ _t('BlogCategoriesWidget.Sort.Label', 'Sort'),
+ array('Title' => 'Title', 'Created' => 'Created', 'LastEdited' => 'Updated')
+ )
+ ->setDescription(
+ _t('BlogCategoriesWidget.Sort.Description', 'Change the order of categories shown by this widget.')
+ );
+
+ $fields[] = DropdownField::create(
+ 'Direction',
+ _t('BlogCategoriesWidget.Direction.Label', 'Direction'),
+ array('ASC' => 'Ascending', 'DESC' => 'Descending')
+ )
+ ->setDescription(
+ _t(
+ 'BlogCategoriesWidget.Direction.Description',
+ 'Change the direction of ordering of categories shown by this widget.'
+ )
+ );
+ });
+
+ return parent::getCMSFields();
+ }
+
+ /**
+ * @return DataList
+ */
+ public function getCategories()
+ {
+ $blog = $this->Blog();
+
+ if (!$blog) {
+ return array();
+ }
+
+ $query = $blog->Categories();
+
+ if ($this->Limit) {
+ $query = $query->limit(Convert::raw2sql($this->Limit));
+ }
+
+ if ($this->Order && $this->Direction) {
+ $query = $query->sort(Convert::raw2sql($this->Order), Convert::raw2sql($this->Direction));
+ }
+
+ return $query;
+ }
+}
+
+
diff --git a/src/Widgets/BlogCategoriesWidgetController.php b/src/Widgets/BlogCategoriesWidgetController.php
new file mode 100644
index 0000000..b891e3a
--- /dev/null
+++ b/src/Widgets/BlogCategoriesWidgetController.php
@@ -0,0 +1,14 @@
+ 'Blog',
+ 'Blog' => Blog::class,
);
/**
@@ -74,7 +81,3 @@ class BlogRecentPostsWidget extends Widget
return array();
}
}
-
-class BlogRecentPostsWidget_Controller extends Widget_Controller
-{
-}
diff --git a/src/Widgets/BlogRecentPostsWidgetController.php b/src/Widgets/BlogRecentPostsWidgetController.php
new file mode 100644
index 0000000..5c0cac0
--- /dev/null
+++ b/src/Widgets/BlogRecentPostsWidgetController.php
@@ -0,0 +1,14 @@
+ 'Blog',
+ 'Blog' => Blog::class,
);
/**
@@ -46,8 +56,11 @@ class BlogTagsCloudWidget extends Widget
* @var FieldList $fields
*/
$fields->push(
- DropdownField::create('BlogID', _t('BlogTagsCloudWidget.Blog',
- 'Blog'), Blog::get()->map())
+ DropdownField::create(
+ 'BlogID',
+ _t('BlogTagsCloudWidget.Blog', 'Blog'),
+ Blog::get()->map()
+ )
);
});
@@ -105,7 +118,3 @@ class BlogTagsCloudWidget extends Widget
return array();
}
}
-
-class BlogTagsCloudWidget_Controller extends Widget_Controller
-{
-}
diff --git a/src/Widgets/BlogTagsCloudWidgetController.php b/src/Widgets/BlogTagsCloudWidgetController.php
new file mode 100644
index 0000000..bfe2f24
--- /dev/null
+++ b/src/Widgets/BlogTagsCloudWidgetController.php
@@ -0,0 +1,13 @@
+ 'Blog',
+ 'Blog' => Blog::class
);
/**
@@ -47,24 +56,44 @@ class BlogTagsWidget extends Widget
{
$this->beforeUpdateCMSFields(function (Fieldlist $fields) {
$fields[] = DropdownField::create(
- 'BlogID', _t('BlogTagsWidget.Blog', 'Blog'), Blog::get()->map()
+ 'BlogID',
+ _t('BlogTagsWidget.Blog', 'Blog'),
+ Blog::get()->map()
);
$fields[] = NumericField::create(
- 'Limit', _t('BlogTagsWidget.Limit.Label', 'Limit'), 0
+ 'Limit',
+ _t('BlogTagsWidget.Limit.Label', 'Limit'),
+ 0
)
- ->setDescription(_t('BlogTagsWidget.Limit.Description', 'Limit the number of tags shown by this widget (set to 0 to show all tags).'))
+ ->setDescription(
+ _t(
+ 'BlogTagsWidget.Limit.Description',
+ 'Limit the number of tags shown by this widget (set to 0 to show all tags).'
+ )
+ )
->setMaxLength(3);
$fields[] = DropdownField::create(
- 'Order', _t('BlogTagsWidget.Sort.Label', 'Sort'), array('Title' => 'Title', 'Created' => 'Created', 'LastEdited' => 'Updated')
+ 'Order',
+ _t('BlogTagsWidget.Sort.Label', 'Sort'),
+ array('Title' => 'Title', 'Created' => 'Created', 'LastEdited' => 'Updated')
)
- ->setDescription(_t('BlogTagsWidget.Sort.Description', 'Change the order of tags shown by this widget.'));
+ ->setDescription(
+ _t('BlogTagsWidget.Sort.Description', 'Change the order of tags shown by this widget.')
+ );
$fields[] = DropdownField::create(
- 'Direction', _t('BlogTagsWidget.Direction.Label', 'Direction'), array('ASC' => 'Ascending', 'DESC' => 'Descending')
+ 'Direction',
+ _t('BlogTagsWidget.Direction.Label', 'Direction'),
+ array('ASC' => 'Ascending', 'DESC' => 'Descending')
)
- ->setDescription(_t('BlogTagsWidget.Direction.Description', 'Change the direction of ordering of tags shown by this widget.'));
+ ->setDescription(
+ _t(
+ 'BlogTagsWidget.Direction.Description',
+ 'Change the direction of ordering of tags shown by this widget.'
+ )
+ );
});
return parent::getCMSFields();
@@ -94,7 +123,3 @@ class BlogTagsWidget extends Widget
return $query;
}
}
-
-class BlogTagsWidget_Controller extends Widget_Controller
-{
-}
diff --git a/src/Widgets/BlogTagsWidgetController.php b/src/Widgets/BlogTagsWidgetController.php
new file mode 100644
index 0000000..07e6f11
--- /dev/null
+++ b/src/Widgets/BlogTagsWidgetController.php
@@ -0,0 +1,14 @@
+
- <% if $Categories.exists %>
- <%t Blog.PostedIn "Posted in" %>
- <% loop $Categories %>
- $Title<% if not Last %>, <% else %>;<% end_if %>
- <% end_loop %>
- <% end_if %>
-
- <% if $Tags.exists %>
- <%t Blog.Tagged "Tagged" %>
- <% loop $Tags %>
- $Title<% if not Last %>, <% else %>;<% end_if %>
- <% end_loop %>
- <% end_if %>
-
- <% if $Comments.exists %>
-
- <%t Blog.Comments "Comments" %>
- $Comments.count
- ;
- <% end_if %>
-
- <%t Blog.Posted "Posted" %>
- $PublishDate.ago
-
- <% if $Credits %>
- <%t Blog.By "by" %>
- <% loop $Credits %><% if not $First && not $Last %>, <% end_if %><% if not $First && $Last %> <%t Blog.AND "and" %> <% end_if %><% if $URLSegment %>$Name.XML<% else %>$Name.XML<% end_if %><% end_loop %>
- <% end_if %>
-
-
"> - $FeaturedImage.setWidth(795) + $FeaturedImage.ScaleWidth(795)
diff --git a/templates/BlogAdminSidebar_holder.ss b/templates/SilverStripe/Blog/Forms/BlogAdminSidebar_holder.ss similarity index 100% rename from templates/BlogAdminSidebar_holder.ss rename to templates/SilverStripe/Blog/Forms/BlogAdminSidebar_holder.ss diff --git a/templates/GridFieldAddByDBField.ss b/templates/SilverStripe/Blog/Forms/GridField/GridFieldAddByDBField.ss similarity index 100% rename from templates/GridFieldAddByDBField.ss rename to templates/SilverStripe/Blog/Forms/GridField/GridFieldAddByDBField.ss diff --git a/templates/forms/TabSet_holder.ss b/templates/SilverStripe/Blog/Forms/TabSet_holder.ss similarity index 93% rename from templates/forms/TabSet_holder.ss rename to templates/SilverStripe/Blog/Forms/TabSet_holder.ss index 85bc11c..dd2337d 100644 --- a/templates/forms/TabSet_holder.ss +++ b/templates/SilverStripe/Blog/Forms/TabSet_holder.ss @@ -1,4 +1,4 @@ -$FeaturedImage.setWidth(795)
- <% end_if %> - -$FeaturedImage.ScaleWidth(795)
+ <% end_if %> + +