Jump to content

FieldtypeQRCode


monollonom
 Share

Recommended Posts

(once again I was surprised to see a work of mine pop up in the newsletter, this time without even listing the module on PW modules website ?. Thx @teppo !)

FieldtypeQRCode

Github: https://github.com/eprcstudio/FieldtypeQRCode
Modules directory: https://processwire.com/modules/fieldtype-qrcode/

A simple fieldtype generating a QR Code from the public URL of the page, and more.

Using the PHP library QR Code Generator by Kazuhiko Arase.

screenshot

Options

In the field’s Details tab you can change between .gif or .svg formats. If you select .svg you will have the option to directly output the markup instead of a base64 image. SVG is the default.

You can also change what is used to generate the QR code and even have several sources. The accepted sources (separated by a comma) are: httpUrl, editUrl, or the name of any text/URL/file/image field.

If LanguageSupport is installed the compatible sources (httpUrl, text field, ...) will return as many QR codes as there are languages. Note however that when outputting on the front-end, only the languages visible to the user will be generated.

Formatting

Unformatted value

When using $page->getUnformatted("qrcode_field") it returns an array with the following structure:

[
	[
		"label" => string,  // label used in the admin
		"qr" => string,     // the qrcode image
		"raw" => string,    // the raw qrcode image (in base64, except if svg+markup)
		"source" => string, // the source, as defined in the configuration
		"text" => string    // and the text used to generate the qrcode
	],
	...
]

Formatted value

The formatted value is an <img>/<svg> (or several right next to each other). There is no other markup.

Should you need the same markup as in the admin you could use:

$field = $fields->get("qrcode_field");
$field->type->markupValue($page, $field, $page->getUnformatted("qrcode_field"));

But it’s a bit cumbersome, plus you need to import the FieldtypeQRCode's css/js. Best is to make your own markup using the unformatted value.

Static QR code generator

You can call FieldtypeQRCode::generateQRCode to generate any QR code you want. Its arguments are:

string $text
bool   $svg    Generate the QR code as svg instead of gif ? (default=true)
bool   $markup If svg, output its markup instead of a base64 ? (default=false)

Hooks

Please have a look at the source code for more details about the hookable functions.

Examples

$wire->addHookAfter("FieldtypeQRCode::getQRText", function($event) {
	$page = $event->arguments("page");
	$event->return = $page->title;
	// or could be: $event->return = "Your custom text";
})
$wire->addHookAfter("FieldtypeQRCode::generateQRCodes", function($event) {
	$qrcodes = $event->return;
	// keep everything except the QR codes generated from editUrl
	foreach($qrcodes as $key => &$qrcode) {
		if($qrcode["source"] === "editUrl") {
			unset($qrcodes[$key]);
		}
	}
	unset($qrcode);
	$event->return = $qrcodes;
})
  • Like 8
  • Thanks 2
Link to comment
Share on other sites

5 hours ago, monollonom said:

this time without even listing the module on PW modules website

Don't mess with @teppo. He sees and knows almost everything and therefore we love him so much (but don't tell him).

Thank you as well for your module. This might and will be a great addition for a lot of us.

  • Like 2
  • Haha 3
Link to comment
Share on other sites

I made a small update where you can now output the QR Code on the front-end by calling the field directly (instead of rendering the inputfield) and I added the option to output the image in either .svg or .gif (if .svg, you'll have the additional ability to output the markup directly, instead of a base64).

  • Like 7
  • Thanks 1
Link to comment
Share on other sites

  • 3 weeks later...
  • 4 months later...

Hi @monollonom - thanks for a very useful module.

One thing I noticed is that render() is called twice. I think this is easily fixed by replacing:

return $this->render();

with:

return $value;

in the sanitizeValue() method.

You can also remove the other two lines from that method also because I don't think you plan is to modify anything in that method.

Thanks!

  • Like 2
Link to comment
Share on other sites

Hi @adrian,

Glad the module is of help and thank you for the feedback!

I applied your suggested changes and at first got an empty output on the front-end. However, taking some cues from @Robin S's FieldtypeRuntimeOnly, I managed to apply the necessary changes for it to work properly.

And as a nice side effect the ___getQRText hook now has access to the current $page!

Thanks again.

  • Like 1
Link to comment
Share on other sites

21 minutes ago, monollonom said:

I applied your suggested changes and at first got an empty output on the front-end

Interesting. I was making use of the ___getQRText so I never an empty output - I expect that was why. 

Thanks for the updates, especially the access to the current page - much nicer than my hack to get it.

Link to comment
Share on other sites

Unfortunately, this new version is still calling the new renderQRCode() method twice. 

I changed both the ___markupValue() and ___wakeupValue() methods to just return $value and everything seems good again. Keep in mind that I haven't tested the output in all scenarios, but it is working in the admin edit process. Probably a good place would be to check in a Lister view to make sure ___markupValue() is working correctly still.

Actually, it looks like @Robin S's RuntimeOnly is calling its renderMarkup() twice so I think it needs some attention as well.

  • Thanks 1
Link to comment
Share on other sites

Okay so I boiled it down to this:

Apparently there's no need to have markupValue() return anything else other than $value as it most likely calls wakeupValue() in any case. Also I went ahead and removed the part hooking into the render() function of the InputfieldMarkup. This removed the double call on the back-end while keeping the front-end call working.

Thanks again, I'm pushing the update right now!

  • Like 3
Link to comment
Share on other sites

3 minutes ago, monollonom said:

Also I went ahead and removed the part hooking into the render() function of the InputfieldMarkup.

I was wondering about the need for that - glad that could also be removed.

Everything looks good here now - thanks again!

  • Thanks 1
Link to comment
Share on other sites

1 hour ago, adrian said:

Actually, it looks like @Robin S's RuntimeOnly is calling its renderMarkup() twice so I think it needs some attention as well.

@adrian, could you please open a GitHub issue or raise this in the RuntimeOnly support thread? I'd like to confirm a few details but don't want to take this thread off-topic.

  • Like 1
Link to comment
Share on other sites

I just published a new release of the Fieldtype and updated the original post with a copy of the README.

I think it's pretty complete at this point: you can output several QR codes by specifying the sources in the field's config (limited to httpUrl, editUrl and PageFiles/PageImages fields), it supports multi-languages by outputting as many QR codes for httpUrl as there are languages (only those visible to the user when output in the front-end), there is now a static function to generate any QR code you want and there are several functions you can hook at to adjust according to your needs.

Let me know if you notice anything strange or a bug!

  • Like 3
Link to comment
Share on other sites

Thanks @monollonom for the new version. One thing I'd like to see is removal of the language dropdown unless "Languages Support - Page Names" is installed. In my case I am using ML, but I don't have language specific URLs, so that dropdown is just confusing.

What do you think?

Thanks.

Link to comment
Share on other sites

This should take care of the language change I am suggesting:

                if($this->wire('modules')->isInstalled('LanguageSupportPageNames')) {
                    $out .= $this->renderSelectOptions($options);
                }

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

48 minutes ago, adrian said:

Something else to be aware of - getting errors when using this with Ryan's TOTP module.

https://github.com/ryancramerdesign/TfaTotp/issues/3

Is this still the case ? I changed the way I import the library by putting it in the __construct rather than outside the class. Also it's weird because in Ryan's case its class is namespaced "Processwire\TfaTotp" so there shouldn't be conflicts ? Or maybe I should use a namespace as well ?

48 minutes ago, adrian said:

This should take care of the language change I am suggesting:
 

if($this->wire('modules')->isInstalled('LanguageSupportPageNames')) {
    $out .= $this->renderSelectOptions($options);
}

Thanks for your suggestion. I don't see any issue to adding this, I'll let you know once it's done.

Maybe it's something to keep in mind to allow to say which language to output from the "source" config input, something like "httpUrl.default" (opening the way to other ways to narrow down what to output for files/images but I'm already getting too far ahead...)

  • Like 1
Link to comment
Share on other sites

2 hours ago, adrian said:

Something else to be aware of - getting errors when using this with Ryan's TOTP module.

https://github.com/ryancramerdesign/TfaTotp/issues/3

Re: this, it seems to be because constants declared using define() do not respect namespace unless explicitely specified. One solution though seems to be to replace define() by const declarations. I'll try to do that tomorrow (also what you suggested is done but I want to also fix this first).

  • Like 2
Link to comment
Share on other sites

Thanks for sorting out the conflicts.

Actually thinking about the ML stuff - maybe my proposed solution isn't the best - sites may still be set up with /en/ /es/ etc as a way of having different language URLs for each page without needing to have LanguageSupportPageNames installed. Maybe you could just add an option to enable or disable the select dropdown instead?

Link to comment
Share on other sites

8 hours ago, adrian said:

Thanks for sorting out the conflicts.

Actually thinking about the ML stuff - maybe my proposed solution isn't the best - sites may still be set up with /en/ /es/ etc as a way of having different language URLs for each page without needing to have LanguageSupportPageNames installed. Maybe you could just add an option to enable or disable the select dropdown instead?

Do you mean like relying on urlSegment instead ?

Implementing your feature I actually came across a situation where it would output the same URL twice because the page name of the root page wasn’t defined in the non-default language. So what I did is to add a check to make sure to not output the same QR code twice (plus the default language will just be labeled “URL”).

Does it sound like it would help in your situation ? Even if not checking for LanguageSupportPageNames.

  • Like 2
Link to comment
Share on other sites

I went ahead and pushed the latest release.

I tested uninstalling LanguageSupportPageNames while still having LanguageSupport and it works as expected, outputting only the default language URL.

I also namespaced the QR code php generator and it should help solve your issue with TOTP.

Let me know if you notice anything else @adrian and otherwise thanks for your feedbacks!

  • Like 3
Link to comment
Share on other sites

I just published another update.

Following a pull request / suggestion from a friend I added support for any text and URL field. Multi-languages support is still there and the field will output as many (non-empty) texts as there are languages. I haven't tested with the textarea field but I assume it will generate the QR code from the raw markup, before any textformatter is applied. I believe this won't be a common use-case, but if need be you can always use hooks to adjust or generate your own QR code.

I also fixed an issue where the template-contextual settings weren't applied.

Please let me know if you run into any issue.

  • Like 1
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

×
×
  • Create New...