Duplicate button for Structure field :)

So I felt the need for a duplicate button for Structure fields.

Here is the solution, it involves editing the core field of the Structure.
So if you deside to use this, be aware that it will not work after you update the panel.
If @bastianallgeier or @texnixe could take a look at it, it would be great and perhaps include it in next release as a option for the field . It works really well.
When you click on the duplicate button, it pops up a duplication of that field with the values in a new modal, if you hit “cancel” nothing happens, if you hit “Ok”, it creates a new entry and puts it right under the one you desided to duplicate. It probably needs some code clean up and styling in the panel but that I leave to the one who deside to use it.

Best regards /

Fred

Steps to make it work:

1. panel/app/fields/structure/structure.php

array(
        'pattern' => '(:any)/duplicate',
        'method'  => 'get|post',
        'action'  => 'duplicate'
      )

2. panel/app/fields/structure/controller.php

public function duplicate($entryId) {

        $self      = $this;
        $field     = $this->field();
        $model     = $this->model();
        $structure = $this->structure($model);
        $entry     = $structure->find($entryId);

        // abort if the field is readonly
        if ($field->readonly) {
            return $this->modal('error', array(
                'text' => l('fields.structure.max.error')
            ));
        }

        if(!$entry) {
            return $this->modal('error', array(
                'text' => l('fields.structure.entry.error')
            ));
        }

        $modalsize = $this->field()->modalsize();
        $form = $this->form('update', array($model, $structure, $entry), function($form) use($model, $structure, $self, $entryId) {

            $form->validate();

            if(!$form->isValid()) {
                return false;
            }

            $data = $form->serialize();
            $structure->duplicate($entryId, $data);
            $self->redirect($model);
        });

        return $this->modal('add', compact('form', 'modalsize'));
    }

3. panel/app/fields/structure/styles/items.php

<a data-modal class="btn btn-with-icon structure-duplicate-button" href="<?php __($field->url($entry->id() . '/duplicate')) ?>">
          <?php i('plus', 'left') ?> Duplicate
      </a>

4. panel/app/fields/structure/styles/table.php

<a data-modal class="btn " href="<?php __($field->url($entry->id() . '/duplicate')) ?>">
              <?php i('plus') ?>
          </a>

5. panel/app/src/panel/structure.php

public function duplicate($id, $data = array()) {
    return $this->store()->duplicate($id, $data);
  }

**6.**panel/app/src/panel/structure/store.php

public function duplicate($id, $data) {

    $data['id'] = str::random(32);

    $key = $id;
    $array = $this->data;

    $offset = array_search($key, array_keys($array)) + 1;

    $result = array_merge (
        array_slice($array, 0, $offset),
        array($data['id'] => $data),
        array_slice($array, $offset, null)
    );

    $this->data = $result;

    $this->save();
    return $data['id'];
  }
1 Like

I do not recommend changing the core. It is possible and in any case much better to make a copy of the field, store it under a different name in /site/fields and extend the original field. This way you can release it as a plugin as well.

2 Likes

Full acknowledgement!