Jump to content
netcarver

Database Counters Module

Recommended Posts

This module provides a very simple interface to a set of named counters. You simply call a single function, next('name'), to pull the next value out of a counter - or to set it up if it does not yet exist. Next() takes a few extra parameters to allow you to increment by values other than 1 or to start at a certain number.

This provides some similar functionality to the built-in page naming feature of PW, and to this module recently posted by Stikki but I think it offers a little more flexibility than either. Having said that, I do like the simplicity of Stikki's new auto-increment module.

Module Availability

Here is my module on Github.

Here it is in the module repository.

Example Usage

Here's how this module can be used to title and name a new page by adding a couple of simple hooks to site/ready.php. This example applies to new pages using a template called 'invoice' that can be quick-added to the page tree. In order to get the following to work, you must edit the template that will be the parent of the 'invoice' template and setup the template for children to "invoice" and set the "Name Format for Children" field to something other than the default blank value (I use  title  as my value.)

<?php

/**
 * Function to recognise our special template.
 */
function isInvoiceTemplate($template) {
    return ($template == 'invoice');
}

/**
 * Pre-load the page title for invoice pages with a unique value
 * which includes a counter component.
 */
$pages->addHookBefore("Pages::setupNew", function($event) {
    $page = $event->arguments(0);

    $is_invoice = isInvoiceTemplate($page->template);
    $no_inv_num = $page->title == '';

    if ($is_invoice && $no_inv_num) {
        $counter_name = 'WR-' . date('Y');
        $number = $this->modules->get('DatabaseCounters')->next($counter_name, 10, 5000);
        $page->title = $counter_name . '-' . sprintf("%06u", $number);
    }
});

/**
 * Prevent ProcessPageEdit from forcing an edit of the name if we got here
 * through a quickAdd from ProcessPageAdd. We can do this because we
 * preset the title field in the Pages::setupNew hook.
 */
$pages->addHookAfter("ProcessPageEdit::loadPage", function($event) {
    $page = $event->return;

    $is_invoice = isInvoiceTemplate($page->template);
    $is_temp    = $page->hasStatus(Page::statusTemp);

    if ($is_invoice && $is_temp) {
        $page->removeStatus(Page::statusTemp);
        $event->return = $page;
    }
});

Note, the above code + module is one direct solution to the problem posted here by RyanJ.

post-465-0-56264100-1459552276_thumb.png

post-465-0-67628000-1459552450_thumb.png

Version History

1.0.0 The initial release.

  • Like 12

Share this post


Link to post
Share on other sites

To extend the above example to hide the name, template and parent fields on the settings page of invoices, you can add the following to the ready.php snippet in the above post.

/**
 * Work out if the template's settings should be tweaked to hide things that should be fixed...
 */
function shouldHideTemplateSettings() {

    // Super users retain super-setting-edit powers
    if (wire('user')->isSuperUser()) {
        return false;
    }

    // Are we even editing a page?
    if (wire('page')->process != 'ProcessPageEdit') {
        return false;
    }

    $id = (int) wire('input')->get('id');
    if (!$id) {
        return false;
    }

    $editedPage = wire('pages')->get($id);
    if ($editedPage->template->flags & Template::flagSystem) {
        return false;
    }

    if (!isInvoiceTemplate($editedPage->template->name)) {
        return false;
    }

    return true;
}

/**
 * Hide some fields from the invoice settings page from non-super-users.
 *
 * There's not much point allowing edits to the name field, so we want it immutable (at least) and probably totally
 * hidden (better.)
 *
 * We don't want invoices being moved from their parent, so we hide the parent field.
 * We don't allow them to use a different template, so we hide the template field.
 *
 */
if (shouldHideTemplateSettings()) {
    $pages->addHookAfter("ProcessPageEdit::buildFormSettings", function($event) {
        $wrapper = $event->return;

        // To show the name field but make it immutable
        $wrapper->_pw_page_name->collapsed = Inputfield::collapsedNoLocked;
        $wrapper->_pw_page_name->description = '';

        // Alternatively, to hide the name field do uncomment the following and comment out the 2 lines above
        //$wrapper->_pw_page_name->collapsed = Inputfield::collapsedHidden;

        // Hide the template changer, invoices can only use the invoice template
        $wrapper->template->collapsed = Inputfield::collapsedHidden;

        // Hide the parent page, as it is fixed in our page structure
        $wrapper->parent_id->collapsed = Inputfield::collapsedHidden;
    });
}
  • Like 6

Share this post


Link to post
Share on other sites

Question of  setupNew page hook  

$pages->addHookBefore("Pages::setupNew"

Instead of creating page at the pw's back-end admin ui, will this page hook be executed if I create a page thru api manually ?

Share this post


Link to post
Share on other sites

Besides of my last question,

I followed the op's setup, but it didn't work at atll

post-2272-0-32536000-1460864209_thumb.pn

post-2272-0-39834500-1460864219_thumb.pn

This is my  /site/ready.php

instead of invoice, i changed it to order

<?php

function isOrderTemplate($template) {
    return ($template == 'order');
}

$pages->addHookBefore("Pages::setupNew", function($event) {
    $page = $event->arguments(0);
 
    $is_order = isOrderTemplate($page->template);
    $no_inv_num = $page->title == '';
 
    if ($is_order && $no_inv_num) {
        $counter_name = 'ORDER-' . date('Y');
        $number = $this->modules->get('DatabaseCounters')->next($counter_name, 10, 5000);
        $page->title = $counter_name . '-' . sprintf("%06u", $number);
    }
});

$pages->addHookAfter("ProcessPageEdit::loadPage", function($event) {
    $page = $event->return;
 
    $is_order = isOrderTemplate($page->template);
    $is_temp    = $page->hasStatus(Page::statusTemp);
 
    if ($is_order && $is_temp) {
        $page->removeStatus(Page::statusTemp);
        $event->return = $page;
    }
});

When I checked back the DatabaseCounter module config,

there is no such a counter named ORDER-   was created

Share this post


Link to post
Share on other sites

I'm curious, the

/site/ready.php

is not executed.

is there any other settings to activated it ?

Share this post


Link to post
Share on other sites

I'm curious, the

/site/ready.php

is not executed.

is there any other settings to activated it ?

None that I know of. Are you sure you have that file in the right place?

From second screen cap, how to make the invoice number (i.e.title field) not editable ?

Edit the template for your order pages in PW. Click on the title (invoice number) field and, on the input tab, set the visibility to whatever you need.

  • Like 2

Share this post


Link to post
Share on other sites

Hi, I was trying this module becuase I this is the solution for my needs, I cant not make it work.

When I click new page I get the same as adrianmak , Title and name are not autopopulated.

 

I know my ready.php is working fine because I was trying this code from another post and the field was being autopopulated with the generated title:

$this->pages->addHookAfter('added', function($event) {
    $page = $event->arguments[0];
    if($page->template != 'your-template-name') return;
    $page->setAndSave('title', 'my page - ' . date("YmdHis"));
});

I'am missing something?


 

Share this post


Link to post
Share on other sites

@Krlos, just writing to acknowledge your post. Please could you send me your site/ready.php file via the forum message system so I could have a look at it tonight? (Please don't post it here.)

Share this post


Link to post
Share on other sites

Hi, I was testing your module and decided to leave it for later. As recheck this part I will send a report.

Thank you.

5 hours ago, netcarver said:

Bump. @Krlos, did you get this working?

 

Share this post


Link to post
Share on other sites

I'm struggling to understand this a bit. In the call to next(), what are 10 and 5000? And are the second and third arguments optional or required?

  • Like 1

Share this post


Link to post
Share on other sites
4 hours ago, stuartsa said:

In the call to next(), what are 10 and 5000? And are the second and third arguments optional or required?

In the case of order numbers - for example - it is common not to start counting form 0 and not to increment by 1. This is a practice to make it harder for the customer to realize that a brand new webshop has just started selling... So as the comment says:

@param int $change (optional) The amount to change the counter by. Must be non-zero integer. Defaults to 1.
@param null|int $min (optional) If specified, the returned value will be greater or equal to this value.

"If specified, the returned value will be greater or equal to this value." actually means: initial starting value.

  • Like 1

Share this post


Link to post
Share on other sites

Hi Netcarver and Ryan and All,

This is exactly what I'm looking for, I think.

I have a client who wants to add page content quickly, with just 3 input field (publish_date, body, tags) and not have to mess with the title or name fields, which we want to default to the page id. Now, one has to type in something like "n" (for new) in those fields, and then change them on the next screen by hand to the generated ID field.

I've programmed a user interface in a previous application (i.e. not using the admin pages), where I would fill in those fields with a temporary random number, and then replace them with the the actual page ids (I probably should have figured out how to grab the auto-increment number instead).

But doing an auto generate function like this for title and name should, in my opinion, be an option in PW, like a setting for a template that says:

"Check here if you want to bypass the title and name fields (on page creation), and have them filled in automatically with the auto-increment ID."

That would be GREAT.

Since that's not real yet, is the code above ready for production use, or is there something that someone else has done that will do this?

Thanks!

Peter

 

Share this post


Link to post
Share on other sites

@Peter Falkenberg Brown

Hello Peter,

I've not used this on a new site in a while (ie, not tested on a recent version of PW) but have no doubts the method works as presented above as I'm using on my own internal site to generate invoice numbers. The version of PW I am using there is 3.0.119.

If your general approach is the same, (given what you wrote above, I can't tell for sure) then I think this could work for you.

Best wishes,
Steve

  • Like 1

Share this post


Link to post
Share on other sites

@netcarver

Thanks, Steve, for your response. I'll dig into it!

@ryan and Ryan and Dev Team: I really do think that this would be a fabulous feature for ProcessWire:

- in every template, have a setting that could turn on a function to fill in the name and title fields with the auto-increment ID automatically, skipping that initial step where you see those two fields, and going right away to the main edit screen, where one would see the title value and the displayed url as the ID number.

In my work with PW, there have been numerous times when I wanted the name and title field to only be the ID, and it was a pain to have to program around that issue.

I think you'd get a LOT of positive feedback about this feature, especially if the setting was also in the API, i.e. add a record without having to specify the title and name field, but have them populated by the auto-increment ID.

Thanks!

Peter

 

Share this post


Link to post
Share on other sites
2 hours ago, Peter Falkenberg Brown said:

skipping that initial step where you see those two fields, and going right away to the main edit screen

There is already a feature similar to this - it's the "Name format for children" setting on the template of the parent page. https://processwire.com/docs/modules/guides/process-template/

ID is not one of the supported options, but if you want the page to be named with the ID you can install @kixe's module which extends the functionality of this feature.
http://modules.processwire.com/modules/process-setup-page-name/

Or you can enter something like a date format ("Y/m/d H:i:s") in the core "Name format for children" setting, which allows you to skip the Page Add step. And then set the page name and title to the ID with a hook in /site/ready.php:

$pages->addHookAfter('added', function(HookEvent $event) {
	$page = $event->arguments(0);
	if($page->template == 'your_child_page_template') {
		$page->setAndSave([
			'name' => $page->id,
			'title' => $page->id,
		]);
	}
});

 

Edited by Robin S
Updated hook for setting multiple page values
  • Like 3

Share this post


Link to post
Share on other sites

@Robin S @netcarver

Hi Robin and Steve,

Robin, the method you outlined above, with the ready.php code, worked perfectly! Thank you!

The module from @kixe generated errors, and after looking at a thread on it, I used your ready.php code instead.

Using the date/time method in the field could, I suppose, encounter a race conflict, but in this case, there's only one admin user.

@ryan

Ryan: I do think this deserves the addition of the id field in the code, and/or a switch option to do this exact function, with the auto-increment id, especially to avoid race conditions.

But... this works for me, today. Thanks again to both of you!

Peter

 

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
      SnipWire - Snipcart integration for ProcessWire
      Snipcart is a powerful 3rd party, developer-first HTML/JavaScript shopping cart platform. SnipWire is the missing link between Snipcart and the content management framework ProcessWire.
      With SnipWire, you can quickly turn any ProcessWire site into a Snipcart online shop. The SnipWire plugin helps you to get your store up and running in no time. Detailed knowledge of the Snipcart system is not required.
      SnipWire is free and open source licensed under Mozilla Public License 2.0! A lot of work and effort has gone into development. It would be nice if you could donate an amount to support further development:

      Status update links (inside this thread) for SnipWire development
      2020-04-06 -- SnipWire 0.8.6 (beta) released! Adds support for Snipcart subscriptions and also fixes some problems 2020-03-21 -- SnipWire 0.8.5 (beta) released! Improves SnipWires webhooks interface and provides some other fixes and additions 2020-03-03 -- SnipWire 0.8.4 (beta) released! Improves compatibility for Windows based Systems. 2020-03-01 -- SnipWire 0.8.3 (beta) released! The installation and uninstallation process has been heavily revised. 2020-02-08 -- SnipWire 0.8.2 (beta) released! Added a feature to change the cart and catalogue currency by GET, POST or SESSION param 2020-02-03 -- SnipWire 0.8.1 (beta) released! All custom classes moved into their own namespaces. 2020-02-01 -- SnipWire is now available via ProcessWire's module directory! 2020-01-30 -- SnipWire 0.8.0 (beta) first public release! (module just submitted to the PW modules directory) 2020-01-28 -- added Custom Order Fields feature (first SnipWire release version is near!) 2020-01-21 -- Snipcart v3 - when will the new cart system be implemented? 2020-01-19 -- integrated taxes provider finished (+ very flexible shipping taxes handling) 2020-01-14 -- new date range picker, discount editor, order notifiactions, order statuses, and more ... 2019-11-15 -- orders filter, order details, download + resend invoices, refunds 2019-10-18 -- list filters, REST API improvements, new docs platform, and more ... 2019-08-08 -- dashboard interface, currency selector, managing Orders, Customers and Products, Added a WireTabs, refinded caching behavior 2019-06-15 -- taxes provider, shop templates update, multiCURL implementation, and more ... 2019-06-02 -- FieldtypeSnipWireTaxSelector 2019-05-25 -- SnipWire will be free and open source Plugin Key Features
      Fast and simple store setup Full integration of the Snipcart dashboard into the ProcessWire backend (no need to leave the ProcessWire admin area) Browse and manage orders, customers, discounts, abandoned carts, and more Multi currency support Custom order and cart fields Process refunds and send customer notifications from within the ProcessWire backend Process Abandoned Carts + sending messages to customers from within the ProcessWire backend Complete Snipcart webhooks integration (all events are hookable via ProcessWire hooks) Integrated taxes provider (which is more flexible then Snipcart own provider) Useful Links
      SnipWire in PW modules directory SnipWire Docs (please note that the documentation is a work in progress) SnipWire @GitHub (feature requests and suggestions for improvement are welcome - I also accept pull requests) Snipcart Website  
      ---- INITIAL POST FROM 2019-05-25 ----
       
    • By bernhard
      #######################
      Please use the new RockFinder2
      #######################
      WHY?
      This module was built to fill the gap between simple $pages->find() operations and complex SQL queries.
      The problem with $pages->find() is that it loads all pages into memory and that can be a problem when querying multiple thousands of pages. Even $pages->findMany() loads all pages into memory and therefore is a lot slower than regular SQL.
      The problem with SQL on the other hand is, that the queries are quite complex to build. All fields are separate tables, some repeatable fields use multiple rows for their content that belong to only one single page, you always need to check for the page status (which is not necessary on regular find() operations and therefore nobody is used to that).
      In short: It is far too much work to efficiently and easily get an array of data based on PW pages and fields and I need that a lot for my RockGrid module to build all kinds of tabular data.

      Basic Usage

       
      Docs & Download
      https://modules.processwire.com/modules/rock-finder/
      https://github.com/BernhardBaumrock/RockFinder
       
      Changelog
      180817, v1.0.6, support for joining multiple finders 180810, v1.0.5, basic support for options fields 180528, v1.0.4, add custom select statement option 180516, change sql query method, bump version to 1.0.0 180515, multilang bugfix 180513, beta release <180513, preview/discussion took place here: https://processwire.com/talk/topic/18983-rocksqlfinder-highly-efficient-and-flexible-sql-finder-module/
    • By MoritzLost
      TrelloWire
      This is a module that allows you to automatically create Trello cards for ProcessWire pages and update them when the pages are updated. This allows you to setup connected workflows. Card properties and change handling behaviour can be customized through the extensive module configuration. Every action the module performs is hookable, so you can modify when and how cards are created as much as you need to. The module also contains an API-component that makes it easy to make requests to the Trello API and build your own connected ProcessWire-Trello workflows.
      Features
      All the things the module can do for you without any custom code: Create a new card on Trello whenever a page is added or published (you can select applicable templates). Configure the target board, target list, name and description for new cards. Add default labels and checklists to the card. Update the card whenever the page is updated (optional). When the status of the card changes (published / unpublished, hidden / unhidden, trashed / restored or deleted), move the card to a different list or archive or delete it (configurable). You can extend this through hooks in many ways: Modifiy when and how cards are created. Modify the card properties (Target board & list, title, description, et c.) before they are sent to Trello. Create your own workflows by utilizing an API helper class with many convenient utility methods to access the Trello API directly. Feedback & Future Plans
      Let me know what you think! In particular:
      If you find any bugs report them here or on Github, I'll try to fix them. This module was born out of a use-case for a client project where we manage new form submissions through Trello. I'm not sure how many use-cases there are for this module. If you do use it, tell me about it! The Trello API is pretty extensive, I'll try to add some more helper methods to the TrelloWireApi class (let me know if you need anything in particular). I'll think about how the module can support different workflows that include Twig – talk to me if you have a use-case! Next steps could be a dashboard to manage pages that are connected to a Trello card, or a new section in the settings tab to manage the Trello connection. But it depends on whether there is any interest in this 🙂 Links
      Repository on Github Complete module documentation (getting started, configuration & API documentation) [Module directory pending approval] Module configuration

    • By MoritzLost
      Process Cache Control
      This module provides a simple solution to clearing all your cache layers at once, and an extensible interface to perform various cache-related actions.
      The simple motivation behind this module was that I was tired of manually clearing caches in several places after deploying a change on a live site. The basic purpose of this module is a simple Clear all caches link in the Setup menu which clears out all caches, no matter where they hide. You can customize what exactly the module does through it's configuration menu:
      Expire or delete all cache entries in the database, or selectively clear caches by namespace ($cache API) Clear the the template render cache. Clear out specific folders inside your site's cache directory (/site/assets/cache) Clear the ProCache page render cache (if your site is using ProCache) Refresh version strings for static assets to bust client-side browser caches (this requires some setup, see the full documentation for details). This is the basic function of the module. However, you can also add different cache management action through the API and execute them through the module's interface. For this advanced usage, the module provides:
      An interface to see all available cache actions and execute them. A system log and logging output on the module page to see verify what the module is doing. A CacheControlTools class with utility functions to clear out different caches. An API to add cache actions, execute them programmatically and even modify the default action. Permission management, allowing you granular control over which user roles can execute which actions. The complete documentation can be found in the module's README.
      Plans for improvements
      If there is some interest in this, I plan to expand this to a more general cache management solution. I particular, I would like to add additional cache actions. Some ideas that came to mind:
      Warming up the template render cache for publicly accessible pages. Removing all active user sessions. Let me know if you have more suggestions!
      Links
      https://github.com/MoritzLost/ProcessCacheControl ProcessCacheControl in the Module directory CHANGELOG in the repository Screenshots


    • By Macrura
      PrevNextTabs Module
      Github: https://github.com/outflux3/PrevNextTabs
      Processwire helper modules for adding page navigation within the editor.
      Overview
      This is a very simple module that adds Previous and Next links inline with the tabs on the page editor. Hovering over the tab shows the title of the previous or next page (using the admin's built in jqueryUI tooltips.)
      Usage
      This module is typically used during development where you or your editors need to traverse through pages for the purpose of proofing, flagging and/or commenting. Rather than returning to the page tree or lister, they can navigate with these links.
      Warnings
      If you are using PW version 2.6.1 or later, the system will prevent you from leaving the page if you have unsaved edits.
      For earlier versions, to avoid accidentally losing changes made to a page that might occur if a user accidentally clicks on one of these, make sure to have the Form Save Reminder module installed.
      http://modules.processwire.com/modules/prev-next-tabs/
×
×
  • Create New...