Jump to content

Problem with Fields, Templates, and Fieldgroups


rick
 Share

Recommended Posts

I have a problem that is making my hair even more gray.

I am writing a process module which constructs seven fields and two templates as shown in this excerpt:

/**
 *** Process Module Install ***
 *
 * The following seven fields are created successfully.
 * No other field attribute nor context is yet defined.
 *
 */

public function ___install() {

	if( !$this->fields->get('field1') ) {
		$f = new Field();
		$f->name = 'field1';
		$f->type = $this->modules->get('FieldtypePageTitle');
		$f->label = __('Title', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field2') ) {
		$f = new Field();
		$f->name = 'field2';
		$f->type = $this->modules->get('FieldtypeText');
		$f->label = __('Text', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field3') ) {
		$f = new Field();
		$f->name = 'field3';
		$f->type = $this->modules->get("FieldtypeTextarea");
		$f->label = __('Text', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field4') ) {
		$f = new Field();
		$f->name = 'field4';
		$f->type = $this->modules->get("FieldtypeImage");
		$f->label = __('Image', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field5') ) {
		$f = new Field();
		$f->name = 'field5';
		$f->type = $this->modules->get('FieldtypePageTitle');
		$f->label = __('Title', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field6') ) {
		$f = new Field();
		$f->name = 'field6';
		$f->type = $this->modules->get("FieldtypeTextarea");
		$f->label = __('Text', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}

	if( !$this->fields->get('field7') ) {
		$f = new Field();
		$f->name = 'field7';
		$f->type = $this->modules->get("FieldtypeImage");
		$f->label = __('Image', __CLASS__);
		$f->description = __('Description.', __CLASS__);
		$f->save();
	}


	/**
	 * Template1 name displays correctly in Setup > Templates.
	 * Template1 shows three assigned fields.
	 * Template1 shows assigned fieldgroup.
	 */
	if( !$this->templates->get('Template1') ) {
		$fg = new Fieldgroup();
		$fg->name = 'Template1';
		$fg->add( $this->fields->get('field1') );
		$fg->add( $this->fields->get('field2') );
		$fg->add( $this->fields->get('field3') );
		$fg->save();

		$t = new Template();
		$t->name = 'Template1';
		$t->fieldgroup = $fg;
		$t->save();
	}

	/**
	 * Template2 name displays correctly in Setup > Templates.
	 * Template2 shows zero (0) assigned fields.
	 * Template2 shows assigned fieldgroup.
	 */
	if( !$this->templates->get('Template2') ) {
		$fg = new Fieldgroup();
		$fg->name = 'Template2';
		$fg->add( $this->fields->get('field4') );
		$fg->add( $this->fields->get('field5') );
		$fg->add( $this->fields->get('field6') );
		$fg->add( $this->fields->get('field7') );
		$fg->save();
		
		$t = new Template();
		$t->name = 'Template2';
		$t->fieldgroup = $fg;
		$t->save();
	}
}

/**
 *** Process Module Uninstall ***
 * 
 */
 
public function ___uninstall() {

	$t = $this->templates->get('Template1');
	if( $t ) {
		$this->templates->delete( $t );
	}
	$fa = array(
		'field1',
		'field2',
		'field3',
		'field4',
	);
	$fg = $this->fieldgroups->get('Template1');
	if( $fg ) { // also tried with, $fg->count > 0, ...
		foreach( $fa as $f ){ // ...and, $fg->items as $f, without $fa array
			$df = $this->fields->get( $f );
			$fg->remove( $df );
			$fg->save();
			wire('fields')->delete( $df );
		}
		$this->fieldgroups->delete( $fg );
	}

	$t = $this->templates->get('Template2');
	if( $t ) {
		$this->templates->delete( $t );
	}
	$fa = array(
		'field5',
		'field6',
		'field7',
	);
	$fg = $this->fieldgroups->get('Template2');
	if( $fg ) {
		foreach( $fa as $f ){
			$df = $this->fields->get( $f );
			$fg->remove( $df );
			$fg->save();
			wire('fields')->delete( $df );
		}
		$this->fieldgroups->delete( $fg );
	}
}

The installation is partially successful in that it creates all seven fields as I have them defined and displays them in the fields list. The two templates are created and display in the templates listing. However, only the first template (Template1) has the three assigned fields listed on the basics tab. Template1 does not list any fields.

The next issue is during uninstall. The templates and fieldgroups are removed, but the fields are not.

There are no errors in the ProcessWire logs, dev console, tracy, or my server logs.

I'm running php7.0, blank ProcessWire 3.0.62, and MySQL 5.0, apache 2.4, on localhost.

 

Can someone offer a suggestion as to what I should be doing differently?

 

Link to comment
Share on other sites

Hi @szabesz,

I have dissected many modules, and used the method described in the related post to gather the properties, which is how I came to create the example. The problem is that the one api-created template functions correctly while the other (with the exact same code) does not. There is something wrong, different, out of order, or whatnot, that I am missing. Of course starring at the problem for hours narrows my tunnel vision even more. :D I need another pair of eyes, and more time during the day. Where does that line form? haha

  • Like 1
Link to comment
Share on other sites

First off I would suggest to call ProcessWire from one type of call. You use wire('fields') and $this->fieldgroups. I am not sure if $this will point to the module class or ProcessWire. You could check this out using a barDump in Tracy:

bd($this);

I would stick to $this->wire() so adding a new template:

$this->wire(new Template);

Or getting other stuff:

$this->wire('fields');

$this->wire('templates');

$this->wire('etcetera');

As an alternative you could check out this example.

  • Like 2
Link to comment
Share on other sites

@rick, when I copied your install method to a test module and corrected the template names to lowercase all the templates and fields were created and assigned without problem. Not sure if the uppercase in the template names would have made a difference - I didn't test that, but probably best to avoid it in any case.

Try this for an uninstall method:

public function ___uninstall() {

    // remove fields from fieldgroups and delete
    $fa = array(
        'field1',
        'field2',
        'field3',
        'field4',
        'field5',
        'field6',
        'field7',
    );
    foreach($fa as $f_name) {
        $f = $this->fields->get($f_name);
        if(!$f) continue;
        $fgroups = $f->getFieldgroups();
        foreach($fgroups as $fgroup) {
            $fgroup->remove($f);
            $fgroup->save();
        }
        $this->fields->delete($f);
    }

    // delete templates
    $ta = array(
        'template1',
        'template2',
    );
    foreach($ta as $t_name) {
        $t = $this->templates->get($t_name);
        if(!$t) continue;
        $this->templates->delete($t);
        $this->fieldgroups->delete($t->fieldgroup); // see http://cheatsheet.processwire.com/templates/methods/templates-delete-template/
    }

}

In your testing, if you have been deleting templates via the API and not removing their associated fieldgroups you may have orphaned items left in the "fieldgroups" database table. You'll have to delete those using phpMyAdmin before you can create new templates using the same names.

It's surprising that the $fieldgroups API variable is almost completely undocumented. It really should be added to the API reference.

  • Like 2
Link to comment
Share on other sites

Hi @arjen,

Thanks for the reply.

I have changed the code to match $this->wire() for fields, fieldgroups, and templates, and I am still getting the same results.

[edit] Robin posted before I finished entering this reply.

@Robin S,

Thanks for the test. Yes I have to remove the orphaned fields manually when the uninstall fails to do so. 

I changed the uninstall to your code source and everything is correctly removed. I also left the field name and template name case unchanged for this test, but I'll change everything to lower-case to match the existing naming convention in the database. Even though the Add New Field option allows upper- and lower-case, and template names match the case of the php template file or whatever you enter for template names without a file.

The only thing I can think of as to why it works now and not before is some typo present in my naming that isn't showing up in phpstorm.

I agree with the lack of documentation too. I've spent three days writing this module and troubleshooting this install/uninstall oddity. I have copied so many forum topic links into module comments for my reference that it should be a book! :D

Thanks for y'alls help. I appreciate it.

 

  • Like 3
Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

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