Recommended Posts

Hey, I'm new and I created a simple module for tagging pages because I didn't found a module for it (sadly this is not a core feature). This module is licensed under the GPL3 and cames with absolutly no warranty at all. You should test the module before using it in production environments. Currently it's an alpha release. if you like the module or have ideas for improvements feel free to post a comment. Currently this fieldtype is only compatible with the Inputfield I've created to because I haven't found  an Inputfield yet, that returns arrays from a single html input.

Greetings Sebi2020

FieldtypeTags.zip.asc

InputfieldTagify.zip

InputfieldTagify.zip.asc

FieldtypeTags.zip

  • Like 4

Share this post


Link to post
Share on other sites

Hello @Sebi2020 , welcome to the forums! 

Could you explain a little further? How your module differs from the standard way of creating tags as pages and using a page field to link the tags to other pages?

 

  • Like 1

Share this post


Link to post
Share on other sites

Nice one @Sebi2020!

Maybe you could look at enhancing the module by allowing the configuration of some Tagify options within the field settings. In particular I'm thinking it would be good to be able to set the "whitelist" and "maxTags" options.

Share this post


Link to post
Share on other sites

@Robin S Thank you for your feedback. In fact I planned to add this features in the next release. I also planned to add autocomplete suggestions based on the already existing tags. 

@Sergio My intention was to store tags in page fields instead of creating a page for every tag you add. By doing so you only need one page/template whcih displays all pages with a given tag. As far as I know the philosophy behind ProcessWire is "Everything is a page" but I don't like to clutter my tree with a page for every tag and in my opinion it's very time consuming to create a page for every tag. 

@flydev Thanks!

Currently I don't know the API very well so I don't know if there is a way to fetch all entries of a given field and not just for the current page.  I would prefer to use the API instead of using the DatabasePDO class.

 

Edited by Sebi2020

Share this post


Link to post
Share on other sites
43 minutes ago, Sebi2020 said:

in my opinion it's very time consuming to create a page for every tag.

Lots of solutions for this from a simple API foreach, to the Batch Child Editor module or even this http://modules.processwire.com/modules/admin-actions-unordered-list-to-pages/

Everyone baulks at the everything is a page at first, but the benefits become apparent and it's actually very elegant and more importantly very flexible if you need to change things down the road.

Not saying there isn't a place for what you have built - just say that there are multiple way to skin a cat 🙂

  • Like 2

Share this post


Link to post
Share on other sites

Most of the page fields (like autocomplete) allow creating new pages on the fly, while editing the actual article page. 

But I totally see place for modules like this (they are always faster to configure for example). 

  • Like 1

Share this post


Link to post
Share on other sites

I just released version 2 of InputfieldTagify:

You can download the zip file from Github:
https://github.com/Sebi2020/InputfieldTagify/releases/tag/v0.0.2

@Robin S

It now supports configuration of predefined whitelist entries (in this case auto-suggestions) and allows you to enable additional delimiters like spaces and semicolons. I plan to include a option for specifying limits on tags in the next release.

Greetings Sebi2020

  • Like 3

Share this post


Link to post
Share on other sites

I've just released a new pre-release of FieldtypeTags and InputfieldTagify

New features include:

  • FieldtypeTags
    • Retrieval of all tags:
      $this('modules')->get('FieldtypeTags')->getAllTags();

       

    • Retrieval of all pages for a specific tag: 
      $this('modules')->get('FieldtypeTags')->getPagesByTag("tagname");

       

  • InputfieldTagify
    • Specification of tag limits

Downloads:
FieldtypeTags v0.1.0-pre: https://github.com/Sebi2020/FieldtypeTags/releases/tag/v0.1.0-pre
InputfieldTagify v0.1.0-pre: https://github.com/Sebi2020/InputfieldTagify/releases/tag/v0.1.0-pre 

Greetings Sebi2020

P.S:  Comments appreciated

Edited by Sebi2020
  • Like 1

Share this post


Link to post
Share on other sites

Thanks for the updates!

I spotted a few little issues in InputfieldTagify...

There are quotes missing around version, autoload and singular in getModuleInfo(): https://github.com/Sebi2020/InputfieldTagify/blob/354acf86ac88baa8c257523cd093ec202c573fe0/InputfieldTagify.module#L18-L20

PHP gives a warning that InputfieldTagify::renderReady() and InputfieldTagify::___processInput() should be compatible with the methods of the Inputfield class that the module extends.

So for renderReady() I think you want:

public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
	$this->addClass("tagify-input");
	return parent::renderReady($parent, $renderValueMode);
}

And for ___processInput():

public function ___processInput(WireInputData $input) {
    //...

 

  • Like 1

Share this post


Link to post
Share on other sites

Thank you for your reply!

2 hours ago, Robin S said:

Thanks for the updates!

I spotted a few little issues in InputfieldTagify...

There are quotes missing around version, autoload and singular in getModuleInfo(): https://github.com/Sebi2020/InputfieldTagify/blob/354acf86ac88baa8c257523cd093ec202c573fe0/InputfieldTagify.module#L18-L20P

Why do you think there must be quotes? ProcessWire  is happy with booleans and integers. Even the core-modules are written in the same way:

		return array(
			'title' => 'Text',
			'version' => 100,
			'summary' => 'Field that stores a single line of text',
			'permanent' => true, 
			);

from wire/modules/Fieldtype/FieldtypeText.module

2 hours ago, Robin S said:

So for renderReady() I think you want:


public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
	$this->addClass("tagify-input");
	return parent::renderReady($parent, $renderValueMode);
}

And for ___processInput():


public function ___processInput(WireInputData $input) {
    //...

 

When do you get this warnings? I cannot reproduce that (with E_ALL enabled in php.ini). 

Which PHP Version did you use? With my Version 7.0.28 everything seems to be fine.

 

Greetings Sebi2020

Share this post


Link to post
Share on other sites
6 minutes ago, Sebi2020 said:

Why do you think there must be quotes? ProcessWire  is happy with booleans and integers. Even the core-modules are written in the same way:


		return array(
			'title' => 'Text',
			'version' => 100,
			'summary' => 'Field that stores a single line of text',
			'permanent' => true, 
			);

from wire/modules/Fieldtype/FieldtypeText.module

I'm talking about the array keys, not the values. If you use a string as an array key the string has to be in quotes or else it is interpreted as a constant. In the FieldtypeText example you show the keys are correctly within quotes.

8 minutes ago, Sebi2020 said:

When do you get this warnings? I cannot reproduce that (with E_ALL enabled in php.ini)

I recommend installing Tracy Debugger - it is good at picking up errors that can otherwise be missed.

2019-02-09_205346.png.4d3a3d166798714cffb86538e3055199.png

Share this post


Link to post
Share on other sites

Oh this was a careless of mine. Thank you for your feedback.

I've just uploaded a new commit which should fix these warnings. I haven't enabled debug mode causing the warnings to be hidden.

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Gadgetto
      Hi,
      for my GroupMailer module I've created a custom Fieldtype + Inputfield module which provides multiple field values. The first field value is a visible text field and there are some other field values which are not presented to user (they are rendered as hidden form fields).

      This is the database schema:
      $schema['data'] = 'text NOT NULL'; // we're using 'data' to represent our 'subject' field $schema['sendstatus'] = 'tinyint NOT NULL DEFAULT 0'; // message send status $schema['recipients'] = "int(10) unsigned NOT NULL DEFAULT 0"; // recipients counter $schema['sent'] = "int(10) unsigned NOT NULL DEFAULT 0"; // sent counter $schema['started'] = "int(10) unsigned NOT NULL DEFAULT 0"; // message sending start $schema['finished'] = "int(10) unsigned NOT NULL DEFAULT 0"; // message sending finished This are the ___wakeupValue and ___sleepValue methods:
      /** * Convert from DB storage to API value. * * @param Page $page * @param Field $field * @param string|int|array $value * @return string|int|array|object $messagemeta * */ public function ___wakeupValue(Page $page, Field $field, $value) { // if for some reason we already get a valid value, then just return it if ($value instanceof MessageMeta) return $value; // start a blank value to be populated $messagemeta = $this->getBlankValue($page, $field); // if we were given a blank value, then we've got nothing to do: just return a blank MessageMeta if (empty($value) || !is_array($value)) return $messagemeta; // create new MessageMeta object $messagemeta = new MessageMeta(); $messagemeta->subject = $value['data']; // @note: we're converting 'data' to 'subject' $messagemeta->sendstatus = $value['sendstatus']; $messagemeta->recipients = $value['recipients']; $messagemeta->sent = $value['sent']; $messagemeta->started = $value['started']; $messagemeta->finished = $value['finished']; return $messagemeta; } /** * Convert from API to DB storage value. * * @param Page $page * @param Field $field * @param string|int|array|object $value * @return array * */ public function ___sleepValue(Page $page, Field $field, $value) { $messagemeta = $value; $sleepValue = array(); // if we are given something other than an MessageMeta, // then just return a blank array if (!$messagemeta instanceof MessageMeta) return $sleepValue; // set MessageMeta to sleepValue $sleepValue = array( 'data' => $messagemeta->subject, // @note: subject is becoming data 'sendstatus' => (int) $messagemeta->sendstatus, 'recipients' => (int) $messagemeta->recipients, 'sent' => (int) $messagemeta->sent, 'started' => (int) $messagemeta->started, 'finished' => (int) $messagemeta->finished, ); return $sleepValue; } Now I try to extend this Fieldtype/Inputfield to provide multi language features.
      Only the first value ("data" which represents the "subject" field) should be/needs to be multi language!
      I had a look at the built in Fieldtypes (e.g FieldtypeText & FieldtypeTextLanguage) which provides multi language support but I couldn't find a similar case (multi-value field with language support). All built in Fieldtypes are single-value fields.
      I know this is a very "general" question but maybe somebody could push me in the right direction?
    • By Anssi
      A simple module to enable easy navigation between the public and the admin side of the site. After installation a green bar will appear to the upper side of the screen, containing a few navigation elements and displaying the PW version number.
      Heavily inspired by @apeisa's great AdminBar (Thanks!). I needed a bit simpler tool for my projects and as a result, this was made. Available on GitHub .

    • By Harmen
      I want to add a few pages to an AsmSelect Page field inside a repeater using the following code:
      $trialsPage = wire("pages")->get(28422); // Get the page $trialsPage->of(false); $newTrial = $ordersPage->trial_repeater_orders->getNewItem(); // Add item to repeater foreach ($selectedProducts as $selectedProduct){ $productPage = $pages->get("template=product, reference=$selectedProduct"); $newTrial->trial_selected_products->add($productPage); } $newTrial->save(); $trialsPage->save(); However, when I check the page where the field is located it doesn't have the new values as expected. The selected pages exist, the field is in the right location, made sure that the output formatting is turned off: $page->of(false); But it still doesn't work with a variable. No matter what I try, it doesn't work.
      It only works when I replace $selectedProduct with a hardcoded string. Am I doing something wrong here?
    • By Sebi
      I've created a small module which lets you define a timestamp after which a page should be accessible. In addition you can define a timestamp when the release should end and the page should not be accessable any more.
      Github: https://github.com/Sebiworld/PageAccessReleasetime
      Usage
      PageAccessReleasetime can be installed like every other module in ProcessWire. Check the following guide for detailed information: How-To Install or Uninstall Modules
      After that, you will find checkboxes for activating the releasetime-fields at the settings-tab of each page. You don't need to add the fields to your templates manually.
      Check e.g. the checkbox "Activate Releasetime from?" and fill in a date in the future. The page will not be accessable for your users until the given date is reached.
      If you have $config->pagefileSecure = true, the module will protect files of unreleased pages as well.
      How it works
      This module hooks into Page::viewable to prevent users to access unreleased pages:
      public function hookPageViewable($event) { $page = $event->object; $viewable = $event->return; if($viewable){ // If the page would be viewable, additionally check Releasetime and User-Permission $viewable = $this->canUserSee($page); } $event->return = $viewable; } To prevent access to the files of unreleased pages, we hook into Page::isPublic and ProcessPageView::sendFile.
      public function hookPageIsPublic($e) { $page = $e->object; if($e->return && $this->isReleaseTimeSet($page)) { $e->return = false; } } The site/assets/files/ directory of pages, which isPublic() returns false, will get a '-' as prefix. This indicates ProcessWire (with activated $config->pagefileSecure) to check the file's permissions via PHP before delivering it to the client.
      The check wether a not-public file should be accessable happens in ProcessPageView::sendFile. We throw an 404 Exception if the current user must not see the file.
      public function hookProcessPageViewSendFile($e) { $page = $e->arguments[0]; if(!$this->canUserSee($page)) { throw new Wire404Exception('File not found'); } } Additionally we hook into ProcessPageEdit::buildForm to add the PageAccessReleasetime fields to each page and move them to the settings tab.
      Limitations
      In the current version, releasetime-protected pages will appear in wire('pages')->find() queries. If you want to display a list of pages, where pages could be releasetime-protected, you should double-check with $page->viewable() wether the page can be accessed. $page->viewable() returns false, if the page is not released yet.
      If you have an idea how unreleased pages can be filtered out of ProcessWire selector queries, feel free to write an issue, comment or make a pull request!