Jump to content

Recommended Posts

Posted

Hello

I would like to add a custom field to template to extend a functionality of MarkupSEO module.

In that module there's a very nice setting that lets you configure a title structure for <title> tag, for example {title}, {sitename} etc.
But this configuration is valid for every template. I thought that it would be better if I can configure this setting by template: in fact for product template I could use {title}, {category} and so on to create a dynamic title. I began to write a module, but I stopped early because of an error. I think this is why I am at the beginning of PW experience and I missed something. I was inspired by this module https://github.com/BitPoet/TemplateParent... the goal is to have two InputfieldTextLanguage (title and description) under the Advanced TAB in Edit Template.

Any idea or suggestion are appreciated, thanks!

Posted

Thank you @kixe!

I've seen that hook and I begun to code a little snippet...

	public function init() {
		$this->addHookAfter("ProcessTemplate::buildEditForm", $this, "appendFieldToForm");
	}
	
	public function appendFieldToForm($event) {

	    $frm = $event->return;
	    $field = $this->modules->get("InputfieldTextLanguage"); 
	    $field->attr('name', 'seo_rule'); 
	    $field->attr('value', $template->seo_rule); 
	    $field->label = $this->_('Seo rule');
	    $field->description = $this->_('If you want to add a custom rule to MarkupSEO'); // Description for field tags
	    $field->notes = $this->_('To define a variable use {title} syntax');
	    $form = $frm->find('id=advanced')->first();
	    $form->insertAfter($field,"tags");  

	}

But when I try to install, viewing a template return me an error on line 35 $field->attr('name', 'seo_rule').... maybe because field doesn't exist?! Don't know how to create :(
 

Posted

From the first view your code has some issues:
1. The variable $template is not defined. This one should work:

$template = $event->argument[0];


2. You cannot use InputfieldTextLanguage here. You need to use InputfieldText and than loop the languages.

$languages = $this->wire('languages');
$field->attr('value', $template->seo_rules);
if($languages) {
     $field->useLanguages = true;
     foreach($languages as $language) $field->set('value' . $language->id, $template->get('seo_rules' . $language->id));
}


3. As far as I know 2nd Argument of function insertAfter() should be an object of type Inputfield you are using a string.

4. in the end you need to overwrite $event->return otherwise there is no change.

If I find some time I will have a deeper look.

Posted

Try this:
 

    public function init() {
        $this->addHookAfter("ProcessTemplate::buildEditForm", $this, "appendFieldToForm");
        $this->addHookBefore("ProcessTemplate::executeSave", function($event) {
            $event->object->template->set('seo_rules', $this->input->post->seo_rules);
            $languages = $this->wire('languages');
            if($languages) {
                foreach($languages as $language) {
                    $event->object->template->set('seo_rules'.$language->id, $this->input->post->{"seo_rules__$language->id"});
                }
            }
        });
    }

    public function appendFieldToForm(HookEvent $event) {

        $languages = $this->wire('languages');
        $template = $event->arguments[0];
        $form = $event->return;

        $field = $this->modules->get("InputfieldText");
        $field->attr('id+name', 'seo_rules');         
        $field->attr('value', $template->seo_rules);
        if($languages) {
             $field->useLanguages = true;
             foreach($languages as $language) $field->set('value' . $language->id, $template->get('seo_rules' . $language->id));
        }
        $field->label = $this->_('Seo rule');
        $field->description = $this->_('If you want to add a custom rule to MarkupSEO'); // Description for field tags
        $field->notes = $this->_('To define a variable use {title} syntax');
        $form->insertAfter($field, $form->tags);

        $event->return =  $form;
    }

 

  • Like 3
Posted

Thanks @kixe. New field is perfectly loaded after tags in advanced tab.

But when I try to save I've got an error
Error: Uncaught Error: Call to a member function set() on null 

on line 

$event->object->template->set('seo_rules', $this->input->post->seo_rules);

 

Error: Uncaught Error: Call to a member function set() on null in

Posted

Solved!!! Hope can be useful :)

This is the class

class SeoTemplate extends WireData implements Module {
	public static function getModuleInfo() {
		return array(
			"title"			=>	"SeoTemplate",
			"summary"		=>	"Module for add seo_rules field to template.",
			"version"		=>	"0.0.1",
			"autoload"		=>	true
		);
	}
	
	public function init() {
		$this->addHookAfter("ProcessTemplate::buildEditForm", $this, "appendFieldToForm");
		$this->addHookBefore("ProcessTemplate::executeSave", $this, "saveSeoRuleField");
	}
	
	public function appendFieldToForm(HookEvent $event) {

		$languages = $this->wire('languages');
		$template = $event->arguments[0];
		$form = $event->return;

	    $field = $this->modules->get("InputfieldText");
    	$field->attr('id+name', 'seo_rules');         
    	$field->attr('value', $template->seo_rules);
    	if($languages) {
			$field->useLanguages = true;
			foreach($languages as $language) $field->set('value' . $language->id, $template->get('seo_rules' . $language->id));
		}
		$field->label = $this->_('Seo rule');
		$field->description = $this->_('If you want to add a custom rule to MarkupSEO');
		$field->notes = $this->_('To define a variable use {title} syntax');
		$form->insertAfter($field, $form->tags);
		
		$event->return = $form;
	}

	public function saveSeoRuleField($event) {
		$template = $this->templates->get($this->input->post->id);
		$template->set('seo_rules', $this->input->post->seo_rules);

		$languages = $this->wire('languages');
		if($languages) {
			foreach($languages as $language) {
				$template->set('seo_rules'.$language->id, $this->input->post->{"seo_rules__$language->id"});
			}
		}
	}
}

 

  • Like 4
Posted

Nice work!

Just in case you would find it cleaner, you can use this version in your site/init.php file rather than setting up an actual module. Sometimes this approach is nicer than having lots of different little helper modules.

        $this->addHookAfter("ProcessTemplate::buildEditForm", function(HookEvent $event) {

            $languages = $this->wire('languages');
            $template = $event->arguments[0];
            $form = $event->return;

            $field = $this->modules->get("InputfieldText");
            $field->attr('id+name', 'seo_rules');         
            $field->attr('value', $template->seo_rules);
            if($languages) {
                $field->useLanguages = true;
                foreach($languages as $language) $field->set('value' . $language->id, $template->get('seo_rules' . $language->id));
            }
            $field->label = $this->_('Seo rule');
            $field->description = $this->_('If you want to add a custom rule to MarkupSEO');
            $field->notes = $this->_('To define a variable use {title} syntax');
            $form->insertAfter($field, $form->tags);
            
            $event->return = $form;
        });

        $this->addHookBefore("ProcessTemplate::executeSave", function() {
            $template = $this->templates->get($this->input->post->id);
            $template->set('seo_rules', $this->input->post->seo_rules);

            $languages = $this->wire('languages');
            if($languages) {
                foreach($languages as $language) {
                    $template->set('seo_rules'.$language->id, $this->input->post->{"seo_rules__$language->id"});
                }
            }
        });

 

  • Like 4
Posted
4 hours ago, nabo said:

But when I try to save I've got an error
Error: Uncaught Error: Call to a member function set() on null Error: Uncaugh Error Call to a member function set() on null in


I didn't know that you need to extend the WireData class. Extending ProcessTemplate this shouldn't happen. 
 

  • Like 1
  • 6 months later...
Posted
On 11/7/2016 at 9:54 AM, kixe said:

Try this:
 



        $form->insertAfter($field, $form->tags);

 

Shouldn't it actually be this?

$form->insertAfter($field, $form->getChildByName('tags'));

 

Posted

Both is possible since InputfieldWrapper::get() calls InputfieldWrapper::getChildByName()

/**
 * assuming $form is a member of InputfieldWrapper class
 * the return of the following api calls are similar
 * if the field exists the return value is an instance of Inputfield otherwise NULL
 */

$form->tags;
$form->get('tags');
$form->getChildByName('tags');

 

  • 1 year later...
Posted
On 11/8/2016 at 1:45 AM, nabo said:

Solved!!! Hope can be useful :)

It worked perfect for me to... for a while. 
Somehow my custom fields remain empty (I think after upgrading my PW version to 3.0.98).

I can still see/use the old values, but when I save a template all the predefined custom fields are cleared and remain empty.
Is anyone experiencing the same thing?

Nevermind... it was my own silly mistake. I only saved values when they returned true on isset().

isset($this->input->post->{$key}) 

Somehow the isset above always returns false even though

echo $this->input->post->{$key};

 returns the actual value.

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...