Jump to content

Unique ID generator


Recommended Posts

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
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

@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
Link to comment
Share on other sites

@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
Link to comment
Share on other sites

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; 
	}
}
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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. 

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