Skip to content

Commit

Permalink
Split link migration for content and field
Browse files Browse the repository at this point in the history
  • Loading branch information
engram-design committed Mar 5, 2023
1 parent 708f08c commit 9b0f638
Show file tree
Hide file tree
Showing 22 changed files with 912 additions and 435 deletions.
32 changes: 28 additions & 4 deletions docs/guides/migrating-from-link.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,39 @@ If your existing site has links from [Link](https://github.com/flipboxfactory/cr

To migrate your link fields and content, install Hyper, and navigate to **Hyper****Settings****Migrations****Link**. You'll need to have Link installed and enabled for this setting to appear.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.
Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.

:::warning
Because the migration needs to modify the content of your elements, this will be a **permanent** modification of your fields and field content. You will be unable to revert back to Link, without restoring your database from a backup.
:::

## Content Migration
## Migration Process
The migration consists of two parts; 1. Migrating your field to Hyper and 2. Migrating the content of elements (entries, etc) to a Hyper Link model.

To achieve this, the migration will **permanently** modify your fields, and the field content for elements. This allows us to provide you with a streamlined and in-place migration without having to create new fields, or go through every occurrence of the field in entries, etc and update link content. All that's required on your end will be updating your Twig templates to work with Hyper.
Because content is stored per-environment, we'll need to re-run any content migrations on each environment. For example, migrating content locally will not change any content on your staging or production installs. Migrated fields will, however due to them being store in Project Config.

## Field Migration
To begin the field migration, you must be on an environment where `allowAdminChanges` is set to `true`.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

You will only need to do this once, as the field changes are store in Project Config.

You can also trigger this via a console command:

```shell
./craft hyper/migrate/link-field
```

## Content Migration
Next, we'll migrate your content. Click the **Migrate Content** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

This step can be re-run on any environment (like staging and production) safely, as Hyper will detect any content that's already been migrated over and skip it.

We **strongly** recommend you run this migration locally first, to ensure the migration runs as expected. You'll need to re-run this on other environments, but it's a good idea to check your content migrates correctly first.

You can also trigger this via a console command:

Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.
```shell
./craft hyper/migrate/link-content
```
32 changes: 28 additions & 4 deletions docs/guides/migrating-from-linkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,39 @@ If your existing site has links from [Linkit](https://github.com/presseddigital/

To migrate your link fields and content, install Hyper, and navigate to **Hyper****Settings****Migrations****Linkit**. You'll need to have Linkit installed and enabled for this setting to appear.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.
Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.

:::warning
Because the migration needs to modify the content of your elements, this will be a **permanent** modification of your fields and field content. You will be unable to revert back to Linkit, without restoring your database from a backup.
:::

## Content Migration
## Migration Process
The migration consists of two parts; 1. Migrating your field to Hyper and 2. Migrating the content of elements (entries, etc) to a Hyper Link model.

To achieve this, the migration will **permanently** modify your fields, and the field content for elements. This allows us to provide you with a streamlined and in-place migration without having to create new fields, or go through every occurrence of the field in entries, etc and update link content. All that's required on your end will be updating your Twig templates to work with Hyper.
Because content is stored per-environment, we'll need to re-run any content migrations on each environment. For example, migrating content locally will not change any content on your staging or production installs. Migrated fields will, however due to them being store in Project Config.

## Field Migration
To begin the field migration, you must be on an environment where `allowAdminChanges` is set to `true`.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

You will only need to do this once, as the field changes are store in Project Config.

You can also trigger this via a console command:

```shell
./craft hyper/migrate/linkit-field
```

## Content Migration
Next, we'll migrate your content. Click the **Migrate Content** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

This step can be re-run on any environment (like staging and production) safely, as Hyper will detect any content that's already been migrated over and skip it.

We **strongly** recommend you run this migration locally first, to ensure the migration runs as expected. You'll need to re-run this on other environments, but it's a good idea to check your content migrates correctly first.

You can also trigger this via a console command:

Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.
```shell
./craft hyper/migrate/linkit-content
```
32 changes: 28 additions & 4 deletions docs/guides/migrating-from-typed-link.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,39 @@ If your existing site has links from [Typed Link](https://github.com/sebastian-l

To migrate your link fields and content, install Hyper, and navigate to **Hyper****Settings****Migrations****Typed Link**. You'll need to have Typed Link installed and enabled for this setting to appear.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.
Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.

:::warning
Because the migration needs to modify the content of your elements, this will be a **permanent** modification of your fields and field content. You will be unable to revert back to Typed Link, without restoring your database from a backup.
:::

## Content Migration
## Migration Process
The migration consists of two parts; 1. Migrating your field to Hyper and 2. Migrating the content of elements (entries, etc) to a Hyper Link model.

To achieve this, the migration will **permanently** modify your fields, and the field content for elements. This allows us to provide you with a streamlined and in-place migration without having to create new fields, or go through every occurrence of the field in entries, etc and update link content. All that's required on your end will be updating your Twig templates to work with Hyper.
Because content is stored per-environment, we'll need to re-run any content migrations on each environment. For example, migrating content locally will not change any content on your staging or production installs. Migrated fields will, however due to them being store in Project Config.

## Field Migration
To begin the field migration, you must be on an environment where `allowAdminChanges` is set to `true`.

Click the **Migrate Fields** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

You will only need to do this once, as the field changes are store in Project Config.

You can also trigger this via a console command:

```shell
./craft hyper/migrate/typed-link-field
```

## Content Migration
Next, we'll migrate your content. Click the **Migrate Content** button to begin the migration process. The next screen will show you the result of the migration and what errors or exceptions were encountered.

This step can be re-run on any environment (like staging and production) safely, as Hyper will detect any content that's already been migrated over and skip it.

We **strongly** recommend you run this migration locally first, to ensure the migration runs as expected. You'll need to re-run this on other environments, but it's a good idea to check your content migrates correctly first.

You can also trigger this via a console command:

Hyper's migrations will automatically take a database backup before the migration begins. If you encounter any errors during the migration, you **must** restore the backup before the migration, before running again.
```shell
./craft hyper/migrate/typed-link-content
```
2 changes: 0 additions & 2 deletions src/Hyper.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@
use craft\elements\db\ElementQuery;
use craft\events\DefineFieldLayoutFieldsEvent;
use craft\events\PopulateElementEvent;
use craft\events\RebuildConfigEvent;
use craft\events\RegisterComponentTypesEvent;
use craft\events\RegisterUrlRulesEvent;
use craft\helpers\ProjectConfig as ProjectConfigHelper;
use craft\helpers\UrlHelper;
use craft\models\FieldLayout;
use craft\services\Elements;
Expand Down
70 changes: 70 additions & 0 deletions src/console/controllers/MigrateController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
namespace verbb\hyper\console\controllers;

use verbb\hyper\migrations\MigrateLinkitField;
use verbb\hyper\migrations\MigrateLinkitContent;
use verbb\hyper\migrations\MigrateTypedLinkField;
use verbb\hyper\migrations\MigrateTypedLinkContent;
use verbb\hyper\migrations\MigrateLinkField;
use verbb\hyper\migrations\MigrateLinkContent;

use Craft;
use craft\helpers\App;

use yii\console\Controller;
use yii\console\ExitCode;

class MigrateController extends Controller
{
// Public Methods
// =========================================================================

public function actionLinkitField(): int
{
return $this->_migrate(MigrateLinkitField::class);
}

public function actionLinkitContent(): int
{
return $this->_migrate(MigrateLinkitContent::class);
}

public function actionTypedLinkField(): int
{
return $this->_migrate(MigrateTypedLinkField::class);
}

public function actionTypedLinkContent(): int
{
return $this->_migrate(MigrateTypedLinkContent::class);
}

public function actionLinkField(): int
{
return $this->_migrate(MigrateLinkField::class);
}

public function actionLinkContent(): int
{
return $this->_migrate(MigrateLinkContent::class);
}


// Private Methods
// =========================================================================

private function _migrate(string $migrationClass): int
{
App::maxPowerCaptain();

Craft::$app->getDb()->backup();

$response = [];

$migration = new $migrationClass();
$migration->setConsoleRequest($this);
$migration->up();

return ExitCode::OK;
}
}
36 changes: 27 additions & 9 deletions src/controllers/MigrationsController.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<?php
namespace verbb\hyper\controllers;

use verbb\hyper\migrations\MigrateLinkit;
use verbb\hyper\migrations\MigrateTypedLink;
use verbb\hyper\migrations\MigrateLink;
use verbb\hyper\migrations\MigrateLinkitField;
use verbb\hyper\migrations\MigrateLinkitContent;
use verbb\hyper\migrations\MigrateTypedLinkField;
use verbb\hyper\migrations\MigrateTypedLinkContent;
use verbb\hyper\migrations\MigrateLinkField;
use verbb\hyper\migrations\MigrateLinkContent;

use Craft;
use craft\helpers\App;
Expand All @@ -16,19 +19,34 @@ class MigrationsController extends Controller
// Public Methods
// =========================================================================

public function actionLinkit(): void
public function actionLinkitField(): void
{
$this->_migrate(MigrateLinkit::class);
$this->_migrate(MigrateLinkitField::class);
}

public function actionTypedLink(): void
public function actionLinkitContent(): void
{
$this->_migrate(MigrateTypedLink::class);
$this->_migrate(MigrateLinkitContent::class);
}

public function actionLink(): void
public function actionTypedLinkField(): void
{
$this->_migrate(MigrateLink::class);
$this->_migrate(MigrateTypedLinkField::class);
}

public function actionTypedLinkContent(): void
{
$this->_migrate(MigrateTypedLinkContent::class);
}

public function actionLinkField(): void
{
$this->_migrate(MigrateLinkField::class);
}

public function actionLinkContent(): void
{
$this->_migrate(MigrateLinkContent::class);
}


Expand Down
4 changes: 2 additions & 2 deletions src/fields/HyperField.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public static function valueType(): string
public ?int $maxLinks = null;
public ?int $fieldLayoutId = null;
public string $columnType = Schema::TYPE_TEXT;
public array $migrationData = [];

private bool $_isStatic = false;
private array $_linkTypes = [];
Expand Down Expand Up @@ -664,9 +665,8 @@ private function _normalizeLayoutConfig(array $config = []): array

$fieldLayoutConfig = ProjectConfig::packAssociativeArrays($fieldLayoutConfig);
$fieldLayoutConfig = ProjectConfig::cleanupConfig($fieldLayoutConfig);
$fieldLayoutConfig = ProjectConfig::unpackAssociativeArrays($fieldLayoutConfig);

return $fieldLayoutConfig;
return ProjectConfig::unpackAssociativeArrays($fieldLayoutConfig);
}

return $layoutConfig;
Expand Down
1 change: 1 addition & 0 deletions src/links/Embed.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use verbb\hyper\Hyper;
use verbb\hyper\base\Link;
use verbb\hyper\models\Settings;

use craft\helpers\Json;
use craft\helpers\Template;
Expand Down
66 changes: 66 additions & 0 deletions src/migrations/MigrateLinkContent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
namespace verbb\hyper\migrations;

use verbb\hyper\fields\HyperField;
use verbb\hyper\links as linkTypes;

use craft\helpers\Console;

use flipbox\craft\link\fields\Link;
use flipbox\craft\link\types\Asset;
use flipbox\craft\link\types\Category;
use flipbox\craft\link\types\Email;
use flipbox\craft\link\types\Entry;
use flipbox\craft\link\types\Url;
use flipbox\craft\link\types\User;

class MigrateLinkContent extends PluginContentMigration
{
// Properties
// =========================================================================

public array $typeMap = [
Asset::class => linkTypes\Asset::class,
Category::class => linkTypes\Category::class,
Email::class => linkTypes\Email::class,
Entry::class => linkTypes\Entry::class,
Url::class => linkTypes\Url::class,
User::class => linkTypes\User::class,
];

public string $oldFieldTypeClass = Link::class;


// Public Methods
// =========================================================================

public function convertModel(HyperField $field, array $oldSettings): bool|array|null
{
$identifier = $oldSettings['identifier'] ?? null;
$linkTypeInfo = $field->migrationData[$identifier] ?? null;
$linkTypeClass = $linkTypeInfo['class'] ?? null;
$linkTypeHandle = $linkTypeInfo['handle'] ?? null;

$hyperType = $oldSettings[0]['type'] ?? null;

if (str_contains($hyperType, 'verbb\\hyper')) {
$this->stdout(' > Content already migrated to Hyper content.', Console::FG_GREEN);

return null;
}

// Return `null` for an empty field, or already migrated to Hyper.
// `false` for when unable to find matching new type.
if (!$linkTypeClass || !$linkTypeHandle) {
return false;
}

$link = new $linkTypeClass();
$link->handle = $linkTypeHandle;
$link->linkValue = $oldSettings['url'] ?? $oldSettings['email'] ?? $oldSettings['elementId'] ?? null;
$link->linkText = $oldSettings['overrideText'] ?? null;
$link->newWindow = ($oldSettings['target'] ?? '') === '_blank';

return [$link->getSerializedValues()];
}
}
Loading

0 comments on commit 9b0f638

Please sign in to comment.