Skip to content

Instantly share code, notes, and snippets.

@jasonvarga

jasonvarga/console.php Secret

Last active Jul 16, 2020
Embed
What would you like to do?
Statamic Beta 20 Migration Helper

Upgrading all the new structure related bits in beta 20

Doesn't support localized structures yet

  • Upgrade to Statamic 3.0.0-beta.20
  • Copy the contents of this gist's console.php into routes/console.php
  • Run php artisan migrate:beta20
  • Delete the command you just copied. It was only temporary.
<?php // copy everything after this line
use Statamic\Facades\File;
use Statamic\Facades\Site;
use Statamic\Support\Str;
use Statamic\Facades\YAML;
class MigrateBetaTwenty
{
protected $console;
public function __construct($console)
{
$this->console = $console;
}
public function migrate()
{
$configPath = config_path('statamic/stache.php');
$contents = File::get($configPath);
$contents = str_replace("'structures' => [", "'navigation' => [", $contents);
$contents = str_replace("'class' => Stores\StructuresStore::class", "'class' => Stores\NavigationStore::class", $contents);
$contents = str_replace("'directory' => base_path('content/structures')", "'directory' => base_path('content/navigation')", $contents);
File::put($configPath, $contents);
$this->console->info('Stache config <comment>config/statamic/stache.php</comment> file updated.');
$collections = collect(File::getFilesByType(base_path('content/collections'), 'yaml'))
->mapWithKeys(function ($path) {
$handle = Str::before(Str::after($path, 'content/collections/'), '.yaml');
$yaml = YAML::file($path)->parse();
return [$handle => compact('path', 'yaml')];
});
$structures = collect(File::getFilesByType(base_path('content/structures'), 'yaml'))
->mapWithKeys(function ($path) {
$handle = Str::before(Str::after($path, 'content/structures/'), '.yaml');
$yaml = YAML::file($path)->parse();
return [$handle => compact('path', 'yaml')];
});
$localizedStructures = collect(File::getFilesByTypeRecursively(base_path('content/structures'), 'yaml'))
->filter(function ($path) {
return substr_count($path, '/') > 2;
})
->mapWithKeys(function ($path) {
$siteAndHandle = Str::before(Str::after($path, 'content/structures/'), '.yaml');
$yaml = YAML::file($path)->parse();
return [$siteAndHandle => compact('path', 'yaml')];
});
$structures = $structures->map(function ($structure) {
$yaml = $structure['yaml'];
$yaml['tree'] = $yaml['tree'] ?? null;
unset($yaml['sites']);
if (! Site::hasMultiple()) {
$yaml = $this->moveRootIntoTree($yaml);
}
unset($yaml['root']);
if (isset($yaml['expects_root'])) {
$yaml['root'] = $yaml['expects_root'];
unset($yaml['expects_root']);
}
// Move tree to end just for readability
$this->moveToEnd($yaml, 'tree');
$structure['yaml'] = $yaml;
return $structure;
});
$localizedStructures->map(function ($structure) {
$yaml = $structure['yaml'];
$yaml = $this->moveRootIntoTree($yaml);
return $structure;
});
// Every structure-managed collection...
$collections->filter(function ($collection) {
return isset($collection['yaml']['structure']);
})->each(function ($collection, $handle) use ($structures, $collections, $localizedStructures) {
$yaml = $collection['yaml'];
// Move contents of the structure inline
$structureHandle = $yaml['structure'];
$structure = $structures[$structureHandle];
unset($structure['yaml']['title']);
if (Site::hasMultiple()) {
$structure['tree'] = [];
foreach ($yaml['sites'] as $site) {
$localized = $localizedStructures["$site/$structureHandle"];
$structure['yaml']['tree'][$site] = $localized['yaml']['tree'];
File::delete($localized['path']);
$localizedStructures->forget("$site/$structureHandle");
}
}
// Move tree to end of the structure, and the structure to the end of the collection, just for readability.
$structure['yaml'] = $this->moveToEnd($structure['yaml'], 'tree');
$yaml['structure'] = $structure['yaml'];
$yaml = $this->moveToEnd($yaml, 'structure');
$structures->forget($structureHandle);
File::delete($structure['path']);
$collection['yaml'] = $yaml;
$collections->put($handle, $collection);
$this->console->info("Structure <comment>$structureHandle</comment> contents has been moved into the <comment>$handle</comment> collection.");
$this->console->info("Structure <comment>{$structure['path']}</comment> has been been deleted.");
});
// Remaining structures should move into navigation directory
File::makeDirectory(base_path('content/navigation'));
$structures->each(function ($structure, $handle) {
$this->moveStructureToNavigation($structure['path']);
$this->console->info("Structure <comment>$handle</comment> has moved into the <comment>content/navigation</comment> directory.");
});
$localizedStructures->each(function ($structure, $siteAndHandle) {
$this->moveStructureToNavigation($structure['path']);
});
// Every orderable collection...
$collections->filter(function ($collection) {
return isset($collection['yaml']['orderable']);
})->each(function ($collection, $handle) use ($collections) {
$yaml = $collection['yaml'];
$structure = ['max_depth' => 1, 'tree' => collect($yaml['entry_order'])->map(function ($entry) {
return compact('entry');
})->all()];
unset($yaml['orderable']);
unset($yaml['entry_order']);
$yaml['structure'] = $structure;
$collection['yaml'] = $yaml;
$collections->put($handle, $collection);
$this->console->info("Collection <comment>$handle</comment> has entry order converted to a single depth inline structure.");
});
$collections->each(function ($collection) {
File::put($collection['path'], YAML::dump($collection['yaml']));
$this->console->info("Collection <comment>{$collection['path']}</comment> written to disk.");
});
File::delete(base_path('content/structures'));
}
protected function moveRootIntoTree($yaml)
{
if (isset($yaml['root'])) {
array_unshift($yaml['tree'], ['entry' => $yaml['root']]);
unset($yaml['root']);
}
return $yaml;
}
protected function moveStructureToNavigation($from)
{
$to = str_replace('content/structures', 'content/navigation', $from);
File::makeDirectory(dirname($to));
File::move($from, $to);
}
protected function moveToEnd($array, $key)
{
$value = $array[$key];
unset($array[$key]);
$array[$key] = $value;
return $array;
}
}
Artisan::command('migrate:beta20', function () {
(new MigrateBetaTwenty($this))->migrate();
});
@icemancast

This comment has been minimized.

Copy link

@icemancast icemancast commented Mar 26, 2020

Beta 19 -> Beta 20 Upgrade

I kept getting a Undefined index: pages error in the console.

I had to remove the content/collections/pages.yaml file so the command could run. After running the migrate command I went into the admin area and created the pages collection so it could regenerate the new yaml structure and all my pages came back.

@AndersMFJ

This comment has been minimized.

Copy link

@AndersMFJ AndersMFJ commented Mar 27, 2020

Is there any way of doing this manually on a multisite? I'm kinda stuck on b19 until then.

@jasonvarga

This comment has been minimized.

Copy link
Owner Author

@jasonvarga jasonvarga commented Apr 1, 2020

Gist has been updated for multisite. Give it another shot.

@AndersMFJ

This comment has been minimized.

Copy link

@AndersMFJ AndersMFJ commented Apr 2, 2020

That worked for the most part, I did get an error about "root page can not have children" but that was easily fixed by hand. Thank you!

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.