Skip to content

Commit

Permalink
NEW: Add task to remove/protect _versions folders
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Carlino committed Sep 24, 2019
1 parent 1df69c4 commit 1308911
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/Dev/Tasks/VersionedFilesMigrationTask.php
@@ -0,0 +1,33 @@
<?php

namespace SilverStripe\Assets\Dev\Tasks;

use SilverStripe\Assets\Dev\VersionedFilesMigrator;
use SilverStripe\Dev\BuildTask;

class VersionedFilesMigrationTask extends BuildTask
{
const STRATEGY_DELETE = 'delete';

const STRATEGY_PROTECT = 'protect';

private static $segment = 'migrate-versionedfiles';

protected $title = 'Migrate versionedfiles';

protected $description = 'If you had the symbiote/silverstripe-versionedfiles module installed on your 3.x site, it
is no longer needed in 4.x as this functionality is provided by default. This task will remove the old _versions
folders or protect them, depending on the strategy you use. Use ?strategy=delete or ?strategy=protect (Apache
only). [Default: delete]';

/**
* @param HTTPRequest $request
*/
public function run($request)
{
$strategy = $request->getVar('strategy') ?: self::STRATEGY_DELETE;
$migrator = VersionedFilesMigrator::create($strategy, ASSETS_PATH, true);
$migrator->migrate();
}

}
195 changes: 195 additions & 0 deletions src/Dev/VersionedFilesMigrator.php
@@ -0,0 +1,195 @@
<?php

namespace SilverStripe\Assets\Dev;

use SilverStripe\Assets\Filesystem;
use SilverStripe\Assets\Storage\AssetStore;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Path;
use SilverStripe\Dev\BuildTask;
use InvalidArgumentException;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;

class VersionedFilesMigrator
{
use Injectable;

const STRATEGY_DELETE = 'delete';

const STRATEGY_PROTECT = 'protect';

/**
* @var array
*/
private static $dependencies = [
'finder' => '%$' . Finder::class,
];

/**
* @var Finder
*/
private $finder;

/**
* @var string
*/
private $basePath = ASSETS_DIR;

/**
* @var string
*/
private $strategy = self::STRATEGY_DELETE;

/**
* @var bool
*/
private $showOutput = true;

/**
* List of logged messages, if $showOutput is false
* @var array
*/
private $log = [];

/**
* VersionedFilesMigrationTask constructor.
* @param string $strategy
* @param string $basePath
* @param bool $output
*/
public function __construct($strategy = self::STRATEGY_DELETE, $basePath = ASSETS_DIR, $output = true)
{
if (!in_array($strategy, [self::STRATEGY_DELETE, self::STRATEGY_PROTECT])) {
throw new InvalidArgumentException(sprintf(
'Invalid strategy: %s',
$strategy
));
}
$this->basePath = $basePath;
$this->strategy = $strategy;
$this->showOutput = $output;
}

/**
* @return void
*/
public function migrate()
{
if ($this->strategy === self::STRATEGY_PROTECT) {
$this->doProtect();
} else {
$this->doDelete();
}
}

/**
* @return void
*/
private function doProtect()
{
foreach ($this->getVersionDirectories() as $path) {
$htaccessPath = Path::join($path, '.htaccess');
if (!file_exists($htaccessPath)) {
$content = "Order deny,allow\nDeny from all";
@file_put_contents($htaccessPath, $content);
if (file_exists($htaccessPath)) {
$this->output("Added .htaccess file to $htaccessPath");
} else {
$this->output("Failed to add .htaccess file to $htaccessPath");
}
}
}
}

/**
* @return void
*/
private function doDelete()
{
foreach ($this->getVersionDirectories() as $path) {
if (!is_dir($path)) {
continue;
}

Filesystem::removeFolder($path);

if (!is_dir($path)) {
$this->output("Deleted $path");
} else {
$this->output("Failed to delete $path");
}
}
}

/**
* @return array
*/
private function getVersionDirectories()
{
$results = $this
->getFinder()
->directories()
->name('_versions')
->in($this->basePath);

$folders = [];

/* @var SplFileInfo $result */
foreach ($results as $result) {
$folders[] = $result->getPathname();
}

return $folders;
}

/**
* @return string
*/
private function nl()
{
return Director::is_cli() ? PHP_EOL : "<br />";
}

/**
* @param string $msg
*/
private function output($msg)
{
if ($this->showOutput) {
echo $msg . $this->nl();
} else {
$this->log[] = $msg;
}
}

/**
* @param Finder $finder
* @return $this
*/
public function setFinder(Finder $finder)
{
$this->finder = $finder;

return $this;
}

/**
* @return Finder
*/
public function getFinder()
{
return $this->finder;
}

/**
* @return array
*/
public function getLog()
{
return $this->log;
}

}
100 changes: 100 additions & 0 deletions tests/php/VersionedFilesMigratorTest.php
@@ -0,0 +1,100 @@
<?php

namespace SilverStripe\Assets\Tests;

use SilverStripe\Assets\Dev\Tasks\VersionedFilesMigrationTask;
use Silverstripe\Assets\Dev\TestAssetStore;
use SilverStripe\Assets\Dev\VersionedFilesMigrator;
use SilverStripe\Assets\File;
use SilverStripe\Assets\FileMigrationHelper;
use SilverStripe\Assets\Filesystem;
use SilverStripe\Assets\Flysystem\FlysystemAssetStore;
use SilverStripe\Assets\Folder;
use SilverStripe\Assets\Tests\FileMigrationHelperTest\Extension;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Path;
use SilverStripe\Dev\SapphireTest;

class VersionedFilesMigratorTest extends SapphireTest
{
protected $usesTransactions = false;

/**
* get the BASE_PATH for this test
*
* @return string
*/
protected function getBasePath()
{
return ASSETS_PATH . '/VersionedFilesMigrationTest';
}


public function setUp()
{
parent::setUp();

TestAssetStore::activate('VersionedFilesMigrationTest/assets');
$dest = TestAssetStore::base_path();
Filesystem::makeFolder(Path::join($dest, 'folder3'));
Filesystem::makeFolder(Path::join($dest, 'folder2', 'subfolder2'));

foreach ($this->getTestVersionDirectories() as $path) {
Filesystem::makeFolder($path);
}
}

public function tearDown()
{
TestAssetStore::reset();
Filesystem::removeFolder($this->getBasePath());
parent::tearDown();
}

/**
* Test delete migration
*/
public function testMigrationDeletes()
{
$migrator = VersionedFilesMigrator::create(
VersionedFilesMigrator::STRATEGY_DELETE,
TestAssetStore::base_path(),
false
);
$migrator->migrate();

foreach ($this->getTestVersionDirectories() as $dir) {
$path = Path::join(BASE_PATH, $dir);
$this->assertFalse(is_dir($path), $dir . ' still exists!');
}
}

/**
* Test protect migration
*/
public function testMigrationProtects()
{
$migrator = VersionedFilesMigrator::create(
VersionedFilesMigrator::STRATEGY_PROTECT,
TestAssetStore::base_path(),
false
);
$migrator->migrate();

foreach ($this->getTestVersionDirectories() as $dir) {
$path = Path::join($dir, '.htaccess');
$this->assertTrue(file_exists($path), $path . ' does not exist');
}
}

private function getTestVersionDirectories()
{
$base = TestAssetStore::base_path();
return [
Path::join($base, 'folder1', '_versions'),
Path::join($base, 'folder2', '_versions'),
Path::join($base, 'folder1', 'subfolder1', '_versions')
];
}
}

0 comments on commit 1308911

Please sign in to comment.