Skip to content

Instantly share code, notes, and snippets.



Last active Aug 8, 2020
What would you like to do?
Statamic Beta 38 Blueprints Migration Helper

Upgrading Blueprints for changes in Beta 38


  • Upgrade to Statamic 3.0.0-beta.38
  • Copy the contents of this gist's console.php into routes/console.php
  • Run php artisan migrate:beta38
  • Delete the command you just copied. It was only temporary.

To confirm it worked:

  • You should see your blueprints organized into subdirectories.
  • The blueprint or blueprints keys inside the yaml files for collections, taxonomies, asset containers, globals, and forms should be removed.
  • If you had a collection/taxonomy with multiple blueprints, they should have appropriate order keys in them.
<?php // copy everything after this line
use Illuminate\Support\Facades\Artisan;
use Statamic\Facades\AssetContainer;
use Statamic\Facades\Blueprint;
use Statamic\Facades\Collection;
use Statamic\Facades\File;
use Statamic\Facades\Form;
use Statamic\Facades\GlobalSet;
use Statamic\Facades\Taxonomy;
use Statamic\Facades\YAML;
use Statamic\Support\Arr;
use Statamic\Support\Str;
class MigrateBetaThirtyEight
protected $console;
protected $usedBlueprints = [];
public function __construct($console)
$this->console = $console;
public function migrate()
Collection::all()->each(function ($collection) {
$this->console->line(" {$collection->title()}");
$this->pluckBlueprintsAndCopy($collection, 'collections/'.$collection->handle(), false);
$collection->queryEntries()->get('blueprint')->map(function ($entry) {
return $entry->get('blueprint');
})->filter()->unique()->each(function ($blueprint) use ($collection) {
$this->copyBlueprint($blueprint, $blueprint, 'collections/'.$collection->handle());
Taxonomy::all()->each(function ($taxonomy) {
$this->console->line(" {$taxonomy->title()}");
$this->pluckBlueprintsAndCopy($taxonomy, 'taxonomies/'.$taxonomy->handle(), false);
$taxonomy->queryTerms()->get('blueprint')->map(function ($entry) {
return $entry->get('blueprint');
})->filter()->unique()->each(function ($blueprint) use ($taxonomy) {
$this->copyBlueprint($blueprint, $blueprint, 'taxonomies/'.$taxonomy->handle());
$this->console->comment('Global Sets:');
GlobalSet::all()->each(function ($set) {
$this->console->line(" {$set->title()}");
$this->pluckBlueprintsAndCopy($set, 'globals', true);
$this->console->comment('Asset Containers:');
AssetContainer::all()->each(function ($container) {
$this->console->line(" {$container->title()}");
[$yaml] = $this->pluckBlueprintsAndCopy($container, 'assets', true, false);
$defaultAssetBlueprint = Blueprint::directory().'/asset.yaml';
if (! isset($yaml['blueprint']) && File::exists($defaultAssetBlueprint)) {
$this->copyBlueprint('asset', $container->handle(), 'assets');
Form::all()->each(function ($form) {
$this->console->line(" {$form->title()}");
$this->pluckBlueprintsAndCopy($form, 'forms', true);
foreach ($this->usedBlueprints as $blueprint) {
if (File::exists($blueprint)) {
$this->console->info('[✓] Blueprint migration complete');
protected function pluckBlueprintsAndCopy($item, $namespace, $useItemHandle, $save = true)
$yaml = YAML::file($item->path())->parse();
$blueprints = Arr::wrap(
Arr::getFirst($yaml, ['blueprint', 'blueprints'], [])
foreach ($blueprints as $i => $blueprint) {
$useItemHandle ? $item->handle() : $blueprint,
count($blueprints) === 1 ? null : $i + 1
$newYaml = $yaml;
unset($newYaml['blueprint'], $newYaml['blueprints']);
if ($save) {
File::put($item->path(), YAML::dump($newYaml));
return [$yaml, $newYaml];
protected function copyBlueprint($oldHandle, $newHandle, $namespace, $order = null)
$original = resource_path('blueprints/'.$oldHandle.'.yaml');
$this->usedBlueprints[] = $original;
if (! File::exists($original)) {
File::makeDirectory($dest = resource_path('blueprints/'.$namespace));
$yaml = YAML::file($original)->parse();
if ($order) {
$yaml['order'] = $order;
File::put($destPath = $dest.'/'.$newHandle.'.yaml', YAML::dump($yaml));
$this->console->line(" <info>[✓]</info> {$this->relativePath($destPath)}");
protected function relativePath($path)
return Str::after($path, Blueprint::directory().'/');
Artisan::command('migrate:beta38', function () {
(new MigrateBetaThirtyEight($this))->migrate();

This comment has been minimized.

Copy link

@admench admench commented Jul 22, 2020

Awesome work with this! Thanks a lot! 🙌🏼


This comment has been minimized.

Copy link

@ghost ghost commented Jul 23, 2020

Flawless, thanks!


This comment has been minimized.

Copy link

@jonassiewertsen jonassiewertsen commented Jul 23, 2020

Good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.