Jump to content

Recommended Posts

Posted

I’m seeking for your advice.

I want to create a module that will allow generating unique IDs to fill different fields (in my specific case page names) according to different templates. Here’s the workflow I’m looking at:

User creates a rule through Configuration -> Field generator that, given a template, will generate an ID. Here’s a mockup:

Omfdldk.png

I’d like if the page name could be automatically set right when the page is created. Also, what do I need to care about when updating the page, is there a risk it can be overwritten and is there a way to prevent that at all. They need to be permanent.

I’d just like to know if it’s possible. I’ve begun looking at the different hooks, but there’s an overwhelming amount of them and I’m not sure where to begin. Would appreciate your input.

  • Like 1
Posted

This is in core. You can skip add page process and have name given automatic.

Where is it? Could you provide a link to documentation, I didn’t find it.

Posted

I may responded too soon without reading carefully on mobile (not seeing screenshot). But there's a template setting only when the children template in family setting is selected. http://processwire.com/api/modules/process-template/

I'm not sure how to archive something you outlined for fields or what the exact need here for this is. But then I'm not sure there's already similar modules, though maybe not on different fields for different templates.

Posted

Maybe some hooks could be around fields or forms, Inputfield::render() Fieldtype::wakeupValue() ProcessPageEdit::buildForm() I'm not sure.

Posted

@Pierre-Luc
 

Take a look at the CryptoPPP library module which has a couple of generator routines (genKeys() and num2string()) that do almost all of what you'll need for this.

Something like...

$output = CryptoPPP::num2string(CryptoPPP::genKeys(), $length, $charset);

...where your $length and $charset choices are controlled by your form entries.

All you need to do, apart from loading the library module, is check that the $output has not previously been generated if you really want to guarantee that it is unique. (The genKeys() routine is a pretty good pseudo random number generator but, as with all random number generators, its output is not guaranteed unique.)

  • Like 4
Posted

@Soma I’ll look into it, it looks like I could simply add some way to make PW aware that it can use a random string generator instead of the date or title.

@netcarver I already have a function that I reuse on every project for this, but I’ll look at your code thanks!

  • Like 1
Posted

I found the code that generates the page name (/wire/core/Pages.php). I’m contemplating making the changes in core and make it more flexible. Thoughts?

if(!$page->name) { 
	// auto-assign a name if possible

	$format = $page->parent()->template->childNameFormat; 
	$pageName = '';

	if(strlen($format)) {

		if($format == 'title') {
			if(strlen($page->title)) $pageName = $page->title; 
				else $pageName = $this->_('untitled'); 

		} else if(!ctype_alnum($format) && !preg_match('/^[-_a-zA-Z0-9]+$/', $format)) {
			// it is a date format
			$pageName = date($format); 
		} else {
			// predefined format
			$pageName = $format; 
		}

	} else if(strlen($page->title)) {
		$pageName = $page->title; 

	} else {
		// no name will be assigned
	}

	if(strlen($pageName)) { 
		// make the name unique

		$pageName = $this->wire('sanitizer')->pageName($pageName, Sanitizer::translate); 
		$numChildren = $page->parent->numChildren();
		$n = 0; 

		do {
			$name = $pageName; 
			if($n > 0) $name .= "-" . ($numChildren+$n); 
			$child = $page->parent->child("name=$name, include=all"); // see if another page already has the same name
			$n++;
		} while($child->id); 

		$page->name = $name; 
	}
}
Posted

I don't think you will need to touch the core at all here.

The code you mentioned is part of the ___setupNew() function. The underscores prefix mean it's hookable. This means you can create a module with your own function that runs before, after or to replace that one.

You can find out about how to do that here: API - Hooks.

  • Like 1
Posted

That’s right, it’s a bit similar and can most probably used for short urls, but I wanted it for different things and flexible enough.

I often have to implement comments, ratings and other things over which I don’t have control on the page name, and I didn’t want to use automatic naming or dates or have to code that every time, just a generic, automatic random string. With this module, I don’t have to worry about it, just make a new page, set title and other fields and it just works by itself, don’t even have to set $page->name!

Posted

For those who want to try it, I have uploaded the project on GitHub. https://github.com/plauclair/FieldGenerator

I strongly recommend you don’t use it in production for now. It runs correctly without problems, but the module doesn’t have an uninstall method yet. Since it creates system templates and fields, you won’t be able to delete those without going through a big hassle.

Currently it also doesn’t have an administration panel, you’ll need to go (in tree) to Admin > Setup > Field generator, and create a new page using the fieldgenerator template. Page title has no effect apart from helping you remember what the rule is.

  • Like 3
Posted

@pierre-luc, there's no reason/need to make fields and template system flag.

Edit: Technically you don't need to "Process implements Module", abstract Process already implements Module.

Posted

Thanks Soma, I just happen to have seen just that in apigen (class implements module). :) 

The reason I am using the system flag is that since the template and fields are required by the module which is part of the system, and that none of those templates or fields should be changed or removed by the user unless the module is uninstalled, it made more sense to make it system to prevent that. Does that make sense?

Posted

I know what it does. Just is it really required to to use template and fields for such a config?

Posted

It doesn't have to be a db table. Modules have already a config interface you could use. No problem if you don't.

Posted

I’ve seen that, but it didn’t seem so flexible to store some kind of repeaters that I can easily loop through. Sure I could implement all config through json but to be honest that sounds way more of a pain than required. 

I really wish there was more documentation about creating modules, especially best practices. 

Posted

Yes agree. It's a lot easier to pull off with pages. :)

I'm not sure about best practice here. Pages of course seems like a good option.

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