Legacy class migration

This commit is contained in:
Damian Mooyman 2015-02-08 20:03:55 +13:00
parent fc8aa0fafe
commit 27cc0f4261
14 changed files with 311 additions and 6 deletions

View File

@ -5,6 +5,8 @@ env:
- DB=MYSQL CORE_RELEASE=3.1
matrix:
allow_failures:
- php: hhvm-nightly
include:
- php: 5.6
env: DB=MYSQL
@ -29,4 +31,4 @@ before_script:
- cd ~/builds/ss
script:
- phpunit silverstripe-blog/tests/
- vendor/bin/phpunit blog/tests/

View File

@ -0,0 +1,72 @@
<?php
/**
* @deprecated since version 2.0
*/
class BlogEntry extends BlogPost implements MigratableObject {
private static $hide_ancestor = 'BlogEntry';
private static $db = array(
"Date" => "SS_Datetime",
"Author" => "Text",
"Tags" => "Text"
);
/**
* Safely split and parse all distinct tags assigned to this BlogEntry
*
* @return array Associative array of lowercase tag to native case tags
* @deprecated since version 2.0
*/
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;
}
public function canCreate($member = null) {
// Deprecated
return false;
}
public function up() {
// Migrate tags
foreach($this->TagNames() as $tag) {
// Skip if tag already assigned
if($this->Tags()->filter('Title', $tag)->count()) continue;
// Create tag
$tagObject = new BlogTag();
$tagObject->Title = $tag;
$tagObject->BlogID = $this->ParentID;
$tagObject->write();
$this->Tags()->add($tagObject);
}
// Update fields
$this->PublishDate = $this->Date;
if($this->ClassName === 'BlogEntry') {
$this->ClassName = 'BlogPost';
$this->write();
}
}
public function requireDefaultRecords() {
parent::requireDefaultRecords();
if(BlogMigrationTask::config()->run_during_dev_build) {
$task = new BlogMigrationTask();
$task->up();
}
}
}
/**
* @deprecated since version 2.0
*/
class BlogEntry_Controller extends BlogPost_Controller {
}

View File

@ -0,0 +1,37 @@
<?php
/**
* @deprecated since version 2.0
*/
class BlogHolder extends BlogTree implements MigratableObject {
private static $hide_ancestor = 'BlogHolder';
private static $db = array(
'AllowCustomAuthors' => 'Boolean',
'ShowFullEntry' => 'Boolean',
);
private static $has_one = array(
'Owner' => 'Member',
);
public function canCreate($member = null) {
// Deprecated
return false;
}
public function up() {
if($this->ClassName === 'BlogHolder') {
$this->ClassName = 'Blog';
$this->write();
}
}
}
/**
* @deprecated since version 2.0
*/
class BlogHolder_Controller extends BlogTree_Controller {
}

View File

@ -0,0 +1,32 @@
<?php
/**
* @deprecated since version 2.0
*/
class BlogTree extends Blog implements MigratableObject {
private static $hide_ancestor = 'BlogTree';
private static $db = array(
'Name' => 'Varchar(255)',
'LandingPageFreshness' => 'Varchar',
);
public function canCreate($member = null) {
// Deprecated
return false;
}
public function up() {
if($this->ClassName === 'BlogTree') {
$this->ClassName = 'Blog';
$this->write();
}
}
}
/**
* @deprecated since version 2.0
*/
class BlogTree_Controller extends Blog_Controller {
}

View File

@ -0,0 +1,73 @@
<?php
/**
* Description of BlogMigrationTask
*
* @author dmooyman
*/
class BlogMigrationTask extends MigrationTask {
/**
* Should this task be invoked automatically via dev/build?
*
* @config
* @var boolean
*/
private static $run_during_dev_build = true;
protected function message($text) {
if(Controller::curr() instanceof DatabaseAdmin) {
DB::alteration_message($text, 'obsolete');
} else {
Debug::message($text);
}
}
public function up() {
$classes = ClassInfo::implementorsOf('MigratableObject');
$this->message('Migrating legacy blog records');
foreach($classes as $class) {
// migrate objects in each stage
if(is_subclass_of($class, 'SiteTree')) {
foreach(array('Stage', 'Live') as $stage) {
$oldMode = Versioned::get_reading_mode();
Versioned::reading_stage($stage);
$this->upClass($class, $stage);
Versioned::set_reading_mode($oldMode);
}
} else {
// Migrate object
$this->upClass($class);
}
}
}
public function down() {
$this->message('BlogMigrationTask::down() not implemented');
}
/**
* Migrate records of a single class
*
* @param type $class
* @param type $stage
*/
protected function upClass($class, $stage = null) {
// Migrate all records
$items = $class::get();
if($count = $items->count()) {
$stageMessage = " in stage {$stage}";
$this->message("Migrating {$count} legacy {$class} records{$stageMessage}.");
foreach($items as $item) {
// Cancel if onBeforeUp returns false
$cancel = $item->extend('onBeforeUp');
if($cancel && min($cancel) === false) continue;
// Up
$item->up();
// Post extensions
$item->extend('onAfterUp');
}
}
}
}

View File

@ -0,0 +1,9 @@
<?php
interface MigratableObject {
/**
* Migrate the object up to the current version
*/
public function up();
}

View File

@ -0,0 +1,28 @@
<?php
if(!class_exists('Widget')) return;
/**
* @deprecated since version 2.0
*/
class ArchiveWidget extends BlogArchiveWidget implements MigratableObject {
private static $db = array(
'DisplayMode' => 'Varchar'
);
private static $only_available_in = array('none');
public function canCreate($member = null) {
// Deprecated
return false;
}
public function up() {
if($this->DisplayMode) {
$this->Type = ($this->DisplayMode === 'year') ? 'Yearly' : 'Monthly';
}
$this->ClassName = 'BlogArchiveWidget';
$this->write();
}
}

View File

@ -0,0 +1,29 @@
<?php
if(! class_exists('Widget')) return;
/**
* A list of tags associated with blog posts
*
* @package blog
*/
class TagCloudWidget extends BlogTagsWidget implements MigratableObject {
private static $db = array(
"Title" => "Varchar",
"Limit" => "Int",
"Sortby" => "Varchar"
);
private static $only_available_in = array('none');
public function canCreate($member = null) {
// Deprecated
return false;
}
public function up() {
$this->ClassName = 'BlogTagsWidget';
$this->write();
}
}

View File

@ -117,7 +117,7 @@ class BlogPost extends Page {
/**
* If no publish date is set, set the date to now.
**/
public function onBeforeWrite() {
protected function onBeforeWrite() {
parent::onBeforeWrite();
if(!$this->PublishDate) $this->setCastedField("PublishDate", time());
}

View File

@ -7,6 +7,9 @@
"silverstripe/cms": "^3.1.0",
"silverstripe/lumberjack": "~1.1"
},
"require-dev": {
"phpunit/PHPUnit": "~3.7@stable"
},
"license": "BSD-2-Clause",
"authors": [
{

View File

@ -9,6 +9,10 @@ class BlogCategoryTest extends FunctionalTest {
parent::setUp();
}
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* Tests that any blog posts returned from $category->BlogPosts() many_many are published,

View File

@ -9,6 +9,11 @@ class BlogPostFilterTest extends SapphireTest {
parent::setUp();
}
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
public function testFilter() {
$member = Member::currentUser();
if($member) $member->logout();

View File

@ -9,6 +9,11 @@ class BlogTagTest extends FunctionalTest {
parent::setUp();
}
public function tearDown() {
SS_Datetime::clear_mock_now();
parent::tearDown();
}
/**
* Tests that any blog posts returned from $tag->BlogPosts() many_many are published,
* both by normal 'save & publish' functionality and by publish date.

View File

@ -5,11 +5,17 @@ class BlogTest extends SapphireTest {
static $fixture_file = "blog.yml";
public function setUp() {
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
parent::setUp();
Config::nest();
SS_Datetime::set_mock_now("2013-10-10 20:00:00");
$this->objFromFixture("Blog", "firstblog")->publish("Stage", "Live");
}
public function tearDown() {
SS_Datetime::clear_mock_now();
Config::unnest();
parent::tearDown();
}
public function testGetExcludedSiteTreeClassNames() {
$member = Member::currentUser();
@ -19,11 +25,11 @@ class BlogTest extends SapphireTest {
Config::inst()->update("BlogPost", "show_in_sitetree", true);
$classes = $blog->getExcludedSiteTreeClassNames();
$this->assertEquals(0, count($classes), "No classes should be hidden.");
$this->assertNotContains('BlogPost', $classes, "BlogPost class should be hidden.");
Config::inst()->update("BlogPost", "show_in_sitetree", false);
$classes = $blog->getExcludedSiteTreeClassNames();
$this->assertEquals(1, count($classes), "BlogPost class should be hidden.");
$this->assertContains('BlogPost', $classes, "BlogPost class should be hidden.");
}