Jump to content

Recommended Posts

Posted

Yesterday I released 0.3.1 with the access migrations like described here:

It does also include a fix to allow usage in multisite setups using $config->paths->site instead of hardcoding /site/….

 

  • Like 2
  • 2 months later...
Posted

I'm making extensive use of migrations for a project and had a question regarding writing migrations for matrix fields.

When creating a new FieldtypeRepeaterMatrix field, I usually need to create two migrations. The first actually creates the blank matrix field, and then the second populates it with types/fields. This is because the template associated with the matrix is not actually created when the initial save() method is called when creating the field. Does anyone know if it is possible to force PW to create this template via the API?

Wanted to also say how useful this module is. Would love to see migrations built into the core one day as it's totally changed how we use PW. I've been thinking about submitting a pull request with some new migration classes I've been building, would be great to have some reusable templates for complex situations like this.

EDIT: I just realized I could probably just create the template as I would any other template on the initial field setup. But if there is an alternative save() method that would let PW handle the template creation that would still seem easier!

  • Like 2
Posted

Replying to myself here in case anyone else was looking for a similar migration. This seems to work for setting up repeater fields via a single migration file. Not sure if the method I've used for generating the repeater template is sensible but it will do for now:

 

<?php

class Migration_2017_10_01_10_10_10 extends FieldMigration {

	public static $description = "<b>+FIELD</b> Custom Matrix (custom_matrix)";

	protected function getFieldName(){ return 'custom_matrix'; }

	protected function getFieldType(){ return 'FieldtypeRepeaterMatrix'; }

	protected function getMatrixTemplateName() {
		return FieldtypeRepeater::templateNamePrefix . $this->getFieldName();
	}

	protected function getMatrixTypes() {
		return [
			[
				'name' => 'foo',
				'label' => 'Foo',
				'head' => '{matrix_label}',
				'fields' => [
					'title' => [
						'label' => 'Title (Optional)',
						'required' => 0,
					],
					'markdown',
				],
			], [
				'name' => 'bar',
				'label' => 'Bar',
				'head' => '{matrix_label}',
				'fields' => [
					'title' => [
						'label' => 'Title (Required)',
						'required' => 0,
					],
					'image',
				],
			],
		];
	}

	protected function addFieldToRepeaterList($matrixField, $field) {
		$repeaterFields = $matrixField->repeaterFields;
		if (!is_array($repeaterFields)) $repeaterFields = [];
		if (!in_array($field->id, $repeaterFields)) {
			$repeaterFields[] = $field->id;
		}
		$matrixField->repeaterFields = $repeaterFields;
	}

	protected function addMatrixType($matrixField, $index, $config) {
		$templateName = $this->getMatrixTemplateName();
		$prefix = 'matrix' . ($index + 1) . '_';

		$matrixField[$prefix.'name'] = $config['name'];
		$matrixField[$prefix.'label'] = $config['label'];
		$matrixField[$prefix.'head'] = $config['head'];
		$matrixField[$prefix.'sort'] = $index;

		$fields = [];
		foreach ($config['fields'] as $key => $property) {
			$field = (!is_numeric($key))
				? $this->fields->get($key)
				: $this->fields->get($property);

			$fields[] = $field->id;
			$this->addFieldToRepeaterList($matrixField, $field);
			$this->insertIntoTemplate($templateName, $field);

			if (!is_numeric($key)) {
				$this->editInTemplateContext($templateName, $field, function(Field $f) use ($property) {
					foreach ($property as $prop => $val) {
						$f->$prop = $val;
					}
				});
			}
		}

		$matrixField[$prefix.'fields'] = $fields;
	}

	protected function fieldSetup(Field $f){
		$f->label = 'Custom Matrix';
		$f->tags = 'matrix';
		$f->required = 1;
		$f->icon = 'fa-bars';

		// Do this to generate a template file for the repeater
		// @TODO Find a better way to do this
		$fieldtype = $f->type;
		$numOldReady = $fieldtype->countOldReadyPages($f);

		// Setup matrix stuff
		$matrixTypes = $this->getMatrixTypes();
		foreach ($matrixTypes as $i => $matrixData) {
			$this->addMatrixType($f, $i, $matrixData);
		}

    // Insert into template
    $template = 'my-template';
		$this->insertIntoTemplate($template, $f);
	}

}

 

  • Like 1
  • 3 weeks later...
Posted

Was about to ask about FiledtypeTable migrations but decided to try myself and it seems to work fine this way, dropping it here in case someone's in need:

 

<?php

class Migration_2017_10_23_12_24_20 extends FieldMigration {

	public static $description = "Add table field";

	protected function getFieldName(){ return 'booking_advanced_fields'; }

	protected function getFieldType(){ return 'Table'; }

	protected function fieldSetup(Field $f){
		$f->label = 'Booking Form Extra Fields';
		$f->collapsed = Inputfield::collapsedNever;
        $this->insertIntoTemplate('home', $f, "booking_advanced", true);
		//Booking advanced is a checkbox in this case, hence the showIf setup to make the table appear if required
        $this->editInTemplateContext('home', $f, function(Field $f) {
            $f->set("showIf","booking_advanced=1");
        });
        $f->set("maxCols", 4);
        
        $f->set("col1name", "column1");
        $f->set("maxCols", 4);
        $f->set("col1type", "text");
        $f->set("col1sort", "1");
        $f->set("col1label", "Column 1 Label");
        $f->set("col1width", 50);
        $f->set("col1settings", "textformatters=TextformatterEntities\nplaceholder=\ndefault=\nmaxLength=2048" );
        
        $f->set("col2name", "column2");
        $f->set("col2type", "text");
        $f->set("col2sort", "2");
        $f->set("col2label", "Column 2 Label");
        $f->set("col2width", 50);
        $f->set("col2settings", "textformatters=TextformatterEntities\nplaceholder=\ndefault=\nmaxLength=2048" );
        $f->save();

        $table_module = wire("modules")->get("FieldtypeTable");

        $table_module->_checkSchema($f, true);
        
	}

}

 

  • Like 2
  • 6 months later...
Posted (edited)

Hello! Thanks for the wonderful module!

Does anyone know, how to use it for FieldtypeOptions? Like picking the type (single or multiple) and setting options values. My attempts for this have failed so far.

@LostKobrakai

Edited by simonsays
Posted

@simonsays Something like that:

class Migration_xxxx_xx_xx_xx_xx_xx extends FieldMigration {

	public static $description = "Create field";

	protected function getFieldName(){ return 'field_name'; }

	protected function getFieldType(){ return 'FieldtypeOptions'; }

	protected function fieldSetup(Field $f){
		$f->label = 'Label';
		$f->inputfieldClass = 'InputfieldRadios';
		$options = <<< _END
34
36
38
40
42
44
46
48
_END;
		$f->type->manager->setOptionsString($f, $options, true);
	}
}

 

  • Like 2
Posted
1 hour ago, LostKobrakai said:

@simonsays Something like that:


class Migration_xxxx_xx_xx_xx_xx_xx extends FieldMigration {

	public static $description = "Create field";

	protected function getFieldName(){ return 'field_name'; }

	protected function getFieldType(){ return 'FieldtypeOptions'; }

	protected function fieldSetup(Field $f){
		$f->label = 'Label';
		$f->inputfieldClass = 'InputfieldRadios';
		$options = <<< _END
34
36
38
40
42
44
46
48
_END;
		$f->type->manager->setOptionsString($f, $options, true);
	}
}

 

Awesome, thanks @LostKobrakai! Saved me a lot of effort and I also became slightly smarter in the process ;)

  • 2 weeks later...
Posted (edited)

@LostKobrakai

When I try to install module using your migration, extra permission declared for this module in getModuleInfo() is not installed automatically.

When I install module via admin, permission is added OK.

Is this a bug? Or was it done like that intentionally?

Edited by simonsays
Posted
On 5/14/2018 at 5:57 PM, LostKobrakai said:

It's certainly not intentional.

https://github.com/LostKobrakai/Migrations/blob/master/classes/ModuleMigration.php

There's what a module migration does. I'd expect that $this->modules->install($name) would also take care about installing any permissions of modules. — I just quickly checked the source and it seems this method should handle that. 

Weird, failed first 2 times, but works perfectly now. Logs did not find anything. Guess, something with my localhost...

Posted

@LostKobrakai

Do you happen to have a good example of adding a repeater field (just the field, no data)?

Found this old thread, which introduces a fairly complex approach, but it is rather old, so I was hoping, that something has changed over the last 4 years.

Looked through FieldtypeRepeater module, but did not find any helpful methods.

  • 6 months later...
Posted (edited)

@LostKobrakai

I have this code for repeater migration, however, I noticed something. Not sure if it is a bug or the way it should be.

<?php

class Migration_2018_11_18_00_00_00_RepeaterAccordionField extends FieldMigration {

    public static $description = "Add repeater for accordion";

    protected function getFieldName() {
        return 'repeater_accordion';
    }

    protected function getFieldType() {
        return 'FieldtypeRepeater';
    }

    protected function fieldSetup(Field $f) {

        $f->label = 'Repeater accordion';
        $f->collapsed = Inputfield::collapsedNever;

        $repeaterFieldGroup = new Fieldgroup();
        $repeaterFieldGroup->name = 'repeater_' . $this->getFieldName();

        //Add fields to fieldgroup - add others as necessary
        $repeaterFieldGroup->append($this->fields->get('title'));
        $repeaterFieldGroup->append($this->fields->get('content_columns'));

        $repeaterFieldGroup->save();

        $repeaterTemplate = new Template();
        $repeaterTemplate->name = 'repeater_' . $this->getFieldName();
        $repeaterTemplate->flags = 8;
        $repeaterTemplate->noChildren = 1;
        $repeaterTemplate->noParents = 1;
        $repeaterTemplate->noGlobal = 1;
        $repeaterTemplate->slashUrls = 1;
        $repeaterTemplate->fieldgroup = $repeaterFieldGroup;

        $repeaterTemplate->save();

        $repeaterPage = "for-field-{$f->id}";
        $f->parent_id = $this->pages->get("name=$repeaterPage")->id;
        $f->template_id = $repeaterTemplate->id;
        $f->repeaterReadyItems = 3;
        
        //Add fields to the repeater - add others as necessary
        $f->repeaterFields = $this->fields->get('title');
        $f->repeaterFields = $this->fields->get('content_columns');

        $f->save();
    }

}

If I rollback the migration, it deletes the field. But does not affect the fieldgroup.

So, when I try to run the migration for the second time - it throws me an integrity violation error (originates from fieldgroups table).

Is this the expected behaviour?

Edited by simonsays
specify
Posted

You can look into the FieldMigration class to see what it does on migration/rollback. It should just remove the field itself. If that doesn‘t clean up the fieldgroup than it‘s expected behaviour. You can still override/add to that by putting your own upgrade/downgrade functions like e.g. I did it here: https://github.com/LostKobrakai/MigrationSnippets/blob/master/Reverse_Template_Migration_Type.php

Posted
16 hours ago, LostKobrakai said:

You can look into the FieldMigration class to see what it does on migration/rollback. It should just remove the field itself. If that doesn‘t clean up the fieldgroup than it‘s expected behaviour. You can still override/add to that by putting your own upgrade/downgrade functions like e.g. I did it here: https://github.com/LostKobrakai/MigrationSnippets/blob/master/Reverse_Template_Migration_Type.php

It was just a quick question to confirm, whether repeater field downgrade works out of the box or requires additional extending.

Thanks for the reply.

  • 1 month later...
Posted

@LostKobrakai

Sorry for noob question, but after installing Migrations module and creating my first migration, my IDE gives an error because the variable $this is unexpected...

image.png.fcf59fbff37fb2b5ce01fd6f3e5da8de.png

It seems like no one else has encounter this...is something wrong with my pw setup? Any hints on where I can look for answers?

Posted

As hinted in the topic on RockMigrations I'll deprecate my module in favor of it. I've added noted to github and this topic:

Quote

This module is deprecated in favor of RockMigrations. It'll continue to work and I might fix some smaller incompatibilities if they're reported, but no major development will happen on this anymore.

 

  • 1 month later...
Posted

I've heard from a few people in the last weeks, which seemed not to happy about by decision in regards to this module and especially the suggestion of RockMigrations as an alternative. Therefore I'll leave a few more thought.

The module has been in it's current state for years. The last commit from my side was from Juli 2017. Just like the module continued to work till today it'll likely do in the future. There might be things to change with new PHP versions or PW versions – but maintaining working condition should be a fairly simple job.

Given that I don't have any active projects anymore using the module (to the most part even for processwire in general) I personally can't and won't deal with keeping the module maintained. My suggestion for supporting RockMigration was mostly based on the fact that it's way more actively maintained and I feel it's better to group efforts behind a single project – especially given the processwire community being on the smaller end – but if RockMigration doesn't work for someone and this module does, feel free to use it. I'd be happy for anyone to pick this up and maintain it going forward, it just won't be me.

/cc @Sascha Nos @elabx

  • Like 4

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...