1

I want to be able to programmatically create a panels page, add a variant and add block plugins to it with specified settings for each block plugin. My ultimate goal is to create a clone of a specified panels page. My current code is

    $page_storage = \Drupal::entityTypeManager()->getStorage('page');
    $variant_storage = \Drupal::entityTypeManager()->getStorage('page_variant');
    $page = $page_storage->load($page_id);
    $variants = $page->getVariants();
    foreach ($variants as $variant) {
        $blocks = $variant->getPluginCollections()['variant_settings']->getConfiguration()['blocks'];
        foreach ($blocks as $block) {
            //Here I have block data. Not sure how to take advantage of it though
        }
    }
    $newPage = $page_storage->create([
        'id' => $new_page_id,
        'label' => $new_page_id,
        'description' => $new_page_id . ' description',
        'path' => '/' . $path,
    ]);
    $newPage->save();
    $newVariant = $variant_storage->create([
        'id' => 'test',
        'label' => 'test',
        'page' => $newPage->id(),
    ]);
    $newVariant->save();

The page does get created just fine but the variant does not get assigned to the page. So I'm not sure what I'm missing. Also even if the variant assignment did work I'm not sure how I'd be able to add and set the config of all the custom blocks I added in the regions. Also I just realized I'm going to have to figure out how to set the layout as well.

How do I programmatically create a page variant and assign it to a programmatically created page, and then programmatically add the block plugins to the variant based on the config of another panels page?

UPDATE: I tried using

$newVariant->setPageEntity($newPage);

to set the variant but it still doesn't show as a variant in page manager. Thought when I

var_dump($newVariant->getPage());

it does seem to show the proper page like so

object(Drupal\page_manager\Entity\Page)#1959 (28) { ["id":protected]=> string(4) "test" ["label":protected]=> string(4) "test"

(that's just a portion) That is when $new_page_id was set to test.


UPDATE 2: I'm attempting to take advantage of the createDuplicate function instead, and at this point just trying to make the variant show up. Not worrying about the blocks yet. This is my new code.

    $variant_storage = \Drupal::entityTypeManager()->getStorage('page_variant');
    $page = $page_storage->load($page_id);

    $id = $page->id();
    $label = $page->label();
    $clone = $page->createDuplicate();
    $clone->set('id', $new_page_id);
    $clone->set('path', $path);
    $clone->set('label', 'Test Page ' . $new_page_id);
    $clone->save();
    $variants = $page->getVariants();
    foreach ($variants as $variant) {
        $var_clone = $variant->createDuplicate();
        $var_clone->set('page', $clone->id());
    }
    $var_clone->save();

However like before, the page gets created but the variant does not get applied.

I tried doubling up and trying multiple methods like so

        $var_clone = $variant->createDuplicate();
        $var_clone->set('page', $clone->id());
        $var_clone->setPageEntity($clone);
        $var_clone->save();

but that also had no effect.


UPDATE 3: I managed to get the variant to show up by setting the id of the variant clone like so

        $hash = bin2hex(random_bytes(8));
        $var_clone = $variant->createDuplicate();
        $var_clone->set('page', $clone->id());
        $var_clone->setPageEntity($clone);
        $var_clone->set('id', $hash);
        $var_clone->save();

It seems like it wasn't saving because an id wasn't set for the variant. However now there are new errors that I receive whenever trying to edit or save the page variant.

Drupal\Core\Config\ConfigDuplicateUUIDException: Attempt to save a configuration entity 'test' with UUID '5d091883-6667-4aab-9fd8-c8ef77c871f4' when this entity already exists with UUID '11066a36-ca97-428f-aa78-f17b034421d8' in Drupal\Core\Config\Entity\ConfigEntityBase->preSave() (line 339 of /mnt/www/html/mysite/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php).


UPDATE 4: I'm now attempting to duplicate the blocks but I can't seem to load the blocks from the variant config.

$conf = $var_clone->getVariantPlugin()->getConfiguration();
$blocks_config = $conf['blocks'];
foreach ($blocks_config as $uuid => $block_data) {
    var_dump($uuid);
    var_dump($block_data);
}

Gives me the UUID but I want to actually have an object instead of an array so I can do

$block_clone = $block->createDuplicateBlock();

But I can't seem to get the block object from the UUID. I've even tried loading by the Uuid specifying every type of entity possible like so.

$conf = $var_clone->getVariantPlugin()->getConfiguration();
$blocks_config = $conf['blocks'];
foreach ($blocks_config as $uuid => $bdata) {
                foreach (array_keys(\Drupal::entityTypeManager()->getDefinitions()) as $etype) {
                    $block = \Drupal::service('entity.repository')->loadEntityByUuid($etype, $uuid);
                    var_dump($block);
                }
}

But I get nothing but NULL when trying to print each attempt at loading the entity by the UUID I got from the variant block configuration. Are config entities loaded a different way? Or does the UUID supplied not refer to something that can be loaded?

1 Answer 1

1

I managed to accomplish this with the following code:

    $path = '/' . $path;
    $page_storage = \Drupal::entityTypeManager()->getStorage('page');
    $variant_storage = \Drupal::entityTypeManager()->getStorage('page_variant');
    $page = $page_storage->load($page_id);

    $id = $page->id();
    $clone = $page->createDuplicate();
    $clone->set('id', $new_page_id);
    $clone->set('path', $path);
    $clone->set('label', $label);
    $clone->save();
    $variants = $page->getVariants();

    foreach ($variants as $variant) {
        $hash = bin2hex(random_bytes(8));
        $var_clone = $variant->createDuplicate();
        $var_clone->set('page', $clone->id());
        $var_clone->setPageEntity($clone);
        $var_clone->set('id', 'variant_id_' . $hash);
        $var_clone->save();

        $conf = $var_clone->getVariantPlugin()->getConfiguration();
        $blocks_config = $conf['blocks'];
        unset($conf['blocks']);
        foreach ($blocks_config as $uuid => $bdata) {
            $hash = bin2hex(random_bytes(8));
            $bdata['uuid'] = $hash;
            $conf['blocks'][$bdata['uuid']] = $bdata;
        }
        $var_clone->getVariantPlugin()->setConfiguration($conf);
        $var_clone->save();
    }

Edit $conf['blocks'][$bdata['uuid']] = $bdata;

1
  • Thanks for sharing, i edited $conf['blocks'[$bdata['uuid']]] = $bdata; to $conf['blocks'][$bdata['uuid']] = $bdata; as an anonymous to make it work. Commented Apr 30, 2019 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.