Jump to content
benbyf

3 new beginner modules

Recommended Posts

Hi!

I've been making my first modules and I've created three so far to help me learn. I would love so feedback or pull requests for improvements as I hope to write a tutorial about my work soon. In particular the third modules isn't very finished.

git: https://github.com/benbyford/PW-starter-modules/

  • HelloUserYouSaved - adds message {your user name, page saved} in admin when a page is saved.

    • This module shows how to implement a basic module,
    • get and use variables,
    • create a message in the admin
  • RedirectAdminPages - redirect specific user role to a custom page set in the module config.

    • This module shows how to implement module configuration,
    • using variables saved in the admin,
    • redirecting a user using session->redirect()
  • HotSwapUser - Swap user on the fly in the admin or frontend of your site

    • This module shows how users can be used in a module
    • how to set a user permission
    • how to install / uninstall something within your module
    • how to create a function that can be output in the frontend of your site.
  • Like 10

Share this post


Link to post
Share on other sites

Hi!

Very good initiative! ^-^

I have skimread through the code and my opinion is: The first and second ones looks good. But to be honest, this hotswap user thing is a big security issue. Sorry! :)

Also only for demonstration / tutorial purposes, it is better not to use hot user swapping as a thema. The audience for beginner tutorials often will be, yes, the name says it: beginners. And assumed they simply do not know about such security issues and best practices in regard of how to validate user-inputs, you should not show code like this to them. At least you would need to embedd all security relevant stuff too. But then it fastly will become to complex for a beginner tutorial. A good one would be to only pick up how to validate user inputs and how PW provides good tools for that. (type and format validation, whitelist matching, ...)

With your code, everyone can login with each existing account (also Superuser) just by knowing / trying (multiple til endless!) user name(s). In regard to this, you may have a look into ALIF or TracyDebugger, how the security for this is tackled there.

I hope you do not mind me my frankness.

-------------

Looking to the code of the users redirect module, you can shorten it a bit. When found a matching user / role, you don't need to store true in a temporary var, break the loop and then check the temporary vars value / state, if you should redirect the current user. You simply can redirect the current user if a role matches:

    /*
    * ___renderPageRedirect
    *
    * redirect user to page if current user role found in config
    */
    public function ___renderPageRedirect($event) {

        // check to see if current page = admin template page
        // otherwise: early return!
        if($this->page->template != "admin") {
            return;
        }

        // find roles set in module configuration and create array
        $roles = explode(',', $this->userRoles);

        // for each user in module config check to see if current user
        foreach ($roles as $key => $val) {
            $roles[$key] = trim($roles[$key]);

            // if current user found then redirect = true
            if($this->user->hasRole($roles[$key])) {

                // this will leave the page and code immediately!
                $this->session->redirect($this->redirectPage);

                // stop user search
                break; // this can stay in here, just as fallback, 
                       // if something went wrong with calling the redirect, 
                       // but normally this line will not get executed.
            }
        }
    }

 

  • Like 4

Share this post


Link to post
Share on other sites

Hi Horst! Thanks for you code amends, will alter now.

I totally agree with you, the third module not really beginner level and needs a heck load more work on it before anyone was to actually use it. The security aspect I'm looking at next and thanks for those links.

Bar the first module, I was trying to make modules that didn't already exist that would be useful and interesting for me to make and had aspects I could teach. If you have any more suggestions for a third module whcih doesn't already exist then I'm all ears.

Thanks,

  • Like 2

Share this post


Link to post
Share on other sites
8 minutes ago, benbyf said:

If you have any more suggestions for a third module whcih doesn't already exist then I'm all ears.

You could write a beginner module about Fieldtype/Inputfield which accept a simple text, save it and render its markup :rolleyes:.

As Horst said, nice initiative !

  • Like 5

Share this post


Link to post
Share on other sites

anyone happen to have any ideas for inputfields that we havent already got??

  • Like 1

Share this post


Link to post
Share on other sites

A simple fieldtype might be "Name", where you enter a firstname and a lastname, which is stored separately and maybe a computed property for the fullname. I think it shouldn't hold more values, as it'll probably become complex just for the amount of fields. 

Also interesting might be other often extended core classes/modules like Process or Textformatter, with the latter actually being quite simple with often just a single method.

  • Like 4

Share this post


Link to post
Share on other sites

I've updated the my modules replacing HotUserSwap with simple TextformatterFindReplace instead. I'm going to work on some field types next :)

  • Like 3

Share this post


Link to post
Share on other sites

It would be good to also work on some Modules that do not 'autoload' :) Thanks for your efforts....

  • Like 1

Share this post


Link to post
Share on other sites

Ok been trying to take on everyones comments. In doing so I've split repos into beginner and intermediate.

https://github.com/benbyford/PW-starter-modules/
https://github.com/benbyford/PW-intermediate-modules

In doing so I can add to them with simple and more complex modules as and when I create them (and learn a new skill). The basic ones are currently super basic, so could probably do a couple more and then stop of crucial things to learn in modeul making. Any more suggestions welcome.

  • Like 5

Share this post


Link to post
Share on other sites

I think composer and dependency mamgement in general is a little out of scope for this series of module creation tutorials, looks interesting though, I've never felt the need for this myself mostly working on small projects and happy using profile exporting and wireshell for different installing / exporting tasks.

Share this post


Link to post
Share on other sites

Would love to see a simple tut on using hooks from a front-end form. Like if a form creates or saves a PW page, can I take the value of a user ID in that saved form/page, and then use that ID to update an altogether different page.

Share this post


Link to post
Share on other sites

Added new module PageDeferredPublish to Intermediate modules - Module allows you to publish a page at a time interval in the future e.g. 24hrs.

  • adds Publish Later buttons to edit page and page tree
  • uses LazyCron to count down pages that are both unpublished and have been checked to publish later
  • when page count down reaches 0, page publishes
     

Screenshot 2016-08-12 10.51.38.png

Screenshot 2016-08-12 10.51.16.png

  • Like 7

Share this post


Link to post
Share on other sites

Great work @benbyf!

I understand you wrote the tutorial to show that the module can do stuff on installing and uninstalling. There is another example you could use to handle creating pages and permissions (more info):

public static function getModuleInfo() {
	return array(

		// Some default stuff
		'title' => 'Title of the module',
		'version' => 001,
		'summary' => 'Summary of the module',
		'autoload' => false,
		'singular' => true,
		'icon' => 'bookmark',
		'permission' => 'name-of-the-permission',

		// Creates the page (and removes after uninstalling)
		'page' => array(
			'name' => 'name-of-the-page',
			'parent' => 'admin', // Or whatever
			'title' => 'Title of the Page',
			),	
		
		// Creates the permission (and removes after uninstalling)
		'permissions' => array(
			'name-of-the-permission' => 'Title of the permission'
			),
	);
}

Written in browser, so not tested. I guess you'll get the idea ;)

Edited by arjen
link added
  • Like 5

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Robin S
      After forgetting the class name of the wonderful AdminPageFieldEditLinks module for what feels like the 100th time I decided I needed to give my failing memory a helping hand...
      Autocomplete Module Class Name
      Provides class name autocomplete suggestions for the "Add Module From Directory" field at Modules > New.
      Requires ProcessWire >= v3.0.16.
      Screencast

      Installation
      Install the Autocomplete Module Class Name module.
      Configuration
      Choose the type of autocomplete options list: "Module class names from directory" or "Custom list of module class names". The latter could be useful if you regularly install some modules and would prefer a shorter list of autocomplete suggestions. The list of class names in the modules directory is generated when the Autocomplete Module Class Name module is installed. It doesn't update automatically (because the retrieval of the class names is quite slow), but you can use the button underneath when you want to retrieve an updated list of class names from the directory. The "fuzzy search" option uses custom filter and item functions for Awesomplete so that the characters you type just have to exist in the module class name and occur after preceding matches but do not need to be contiguous. Uncheck this option if you prefer the standard Awesomplete matching. Custom settings for Awesomplete can be entered in the "Awesomplete options" field if needed. See the Awesomplete documentation for more information.  
      https://github.com/Toutouwai/AutocompleteModuleClassName
      https://modules.processwire.com/modules/autocomplete-module-class-name/
    • By teppo
      MarkupMenu is a markup module for generating menu trees. When provided a root page as a starting point, it generates a navigation tree (by default as a HTML "<ul>" element wrapped by a "<nav>" element) from that point onwards. If you've also provided it with current (active) page, the menu will be rendered accordingly, with current item highlighted and items rendered up to that item and its children (unless you disable the "collapsed" option, in which case the full page tree will be rendered instead).
      Modules directory: https://modules.processwire.com/modules/markup-menu/ GitHub repository: https://github.com/teppokoivula/MarkupMenu Usage
      As a markup module, MarkupMenu is intended for front-end use, but you can of course use it in a module as well. Typically you'll only need the render() method, which takes an array of options as its only argument:
      echo $modules->get('MarkupMenu')->render([ 'root_page' => $pages->get(1), 'current_page' => $page, ]); Note: if you omit root_page, site root page is used by default. If you omit current_page, the menu will be rendered, but current (active) page won't be highlighted etc.
      A slightly more complex example, based on what I'm using on one of my own sites to render a (single-level) top menu:
      echo $modules->get('MarkupMenu')->render([ 'current_page' => $page, 'templates' => [ 'nav' => '<nav class="{classes} menu--{menu_class_modifier}" aria-label="{aria_label}">%s</nav>', 'item_current' => '<a class="menu__item menu__item--current" href="{item.url}" tabindex="0" aria-label="Current page: {item.title}">{item.title}</a>', ], 'placeholders' => [ 'menu_class_modifier' => 'top', 'aria_label' => 'Main navigation', ], 'include' => [ 'root_page' => true, ], 'exclude' => [ 'level_greater_than' => 1, ], ]); Note: some things you see above may not be entirely sensible, such as the use of {menu_class_modifier} and {aria_label} placeholders. On the actual site the "nav" template is defined in site config, so I can define just these parts on a case-by-case basis while actual nav markup is maintained in one place.
      Please check out the README file for available render options. I'd very much prefer not to keep this list up to date in multiple places. Basically there are settings for defining "templates" for different parts of the menu (list, item, etc.), include array for defining rules for including in the menu and exclude array for the opposite effect, classes and placeholders arrays for overriding default classes and injecting custom placeholders, etc. 🙂
      MarkupMenu vs. MarkupSimpleNavigation
      TL;DR: this is another take on the same concept. There are many similarities, but also some differences – especially when it comes to the supported options and syntax. If you're currently using MarkupSimpleNavigation then there's probably no reason to switch over.
      I'd be surprised if anyone didn't draw lines between this module and Soma's awesome MarkupSimpleNavigation. Simply put, I've been using MSN (...) for a number of years, and it's been great – but there have been some smallish issues with it, particularly with the markup generation part, and it's also doing some things in a way that just doesn't work for me – the xtemplates thing being one of these. In many ways it's less about features, and more about style.
      In MarkupMenu I've tried to correct these little hiccups, modernise the default markup, and allow for more flexibility with placeholder variables and additional / different options. MarkupMenu was built for ProcessWire 3.0.112+ and PHP 7.1+, it's installable with Composer, and I have a few additional ideas (such as conditional placeholders) on my todo list.
      One smallish and rather specific difference is that MarkupMenu supports overriding default options via $config->MarkupMenu. I find myself redefining the default markup for every site, which until now meant that each site has a wrapper function for MarkupSimpleNavigation (to avoid code / config repetition), and this way I've been able to omit that 🙂
      Requirements
      ProcessWire >= 3.0.112 PHP >= 7.1.0 If you're working on an earlier version of ProcessWire or PHP, use MarkupSimpleNavigation instead.
    • By Robin S
      Repeater Images
      Adds options to modify Repeater fields to make them convenient for "page-per-image" usage. Using a page-per-image approach allows for additional fields to be associated with each image, to record things such as photographer, date, license, links, etc.
      When Repeater Images is enabled for a Repeater field the module changes the appearance of the Repeater inputfield to be similar (but not identical) to an Images field. The collapsed view shows a thumbnail for each Repeater item, and items can be expanded for field editing.
      Screencast

      Installation
      Install the Repeater Images module.
      Setup
      Create an image field to use in the Repeater field. Recommended settings for the image field are "Maximum files allowed" set to 1 and "Formatted value" set to "Single item (null if empty)". Create a Repeater field. Add the image field to the Repeater. If you want additional fields in the Repeater create and add these also. Repeater Images configuration
      Tick the "Activate Repeater Images for this Repeater field" checkbox. In the "Image field within Repeater" dropdown select the single image field. You must save the Repeater field settings to see any newly added Image fields in the dropdown. Adjust the image thumbnail height if you want (unlike the core Images field there is no slider to change thumbnail height within Page Edit). Note: the depth option for Repeater fields is not compatible with the Repeater Images module.
      Image uploads feature
      There is a checkbox to activate image uploads. This feature allows users to quickly and easily add images to the Repeater Images field by uploading them to an adjacent "upload" field.
      To use this feature you must add the image field selected in the Repeater Images config to the template of the page containing the Repeater Images field - immediately above or below the Repeater Images field would be a good position.
      It's recommended to set the label for this field in template context to "Upload images" or similar, and set the visibility of the field to "Closed" so that it takes up less room when it's not being used. Note that when you drag images to a closed Images field it will automatically open. You don't need to worry about the "Maximum files allowed" setting because the Repeater Images module overrides this for the upload field.
      New Repeater items will be created from the images uploaded to the upload field when the page is saved. The user can add descriptions and tags to the images while they are still in the upload field and these will be retained in the Repeater items. Images are automatically deleted from the upload field when the page is saved.
      Tips
      The "Use accordion mode?" option in the Repeater field settings is useful for keeping the inputfield compact, with only one image item open for editing at a time. The "Repeater item labels" setting determines what is shown in the thumbnail overlay on hover. Example for an image field named "image": {image.basename} ({image.width}x{image.height})  
      https://github.com/Toutouwai/RepeaterImages
      https://modules.processwire.com/modules/repeater-images/
    • By EyeDentify
      Hello There Guys.

      I am in the process of getting into making my first modules for PW and i had a question for you PHP and PW gurus in here.

      I was wondering how i could use an external library, lets say TwitterOAuth in my PW module.
      Link to library
      https://twitteroauth.com/

      Would the code below be correct or how would i go about this:
      <?PHP namespace ProcessWire; /* load the TwitterOAuth library from my Module folder */ require "twitteroauth/autoload.php"; use Abraham\TwitterOAuth\TwitterOAuth; class EyeTwitter extends WireData,TwitterOAuth implements Module { /* vars */ protected $twConnection; /* extend parent TwitterOAuth contructor $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token, $access_token_secret); */ public function myTwitterConnection ($consumer_key, $consumer_secret, $access_token, $access_token_secret) { /* save the connection for use later */ $this->twConnection = TwitterOAuth::__construct($consumer_key, $consumer_secret, $access_token, $access_token_secret); } } ?> Am i on the right trail here or i am barking up the wrong tree?
      I don´t need a complete solution, i just wonder if i am including the external library the right way.
      If not, then give me a few hint´s and i will figure it out.

      Thanks a bunch.

      /EyeDentify
    • By dimitrios
      Hello,
      this module can publish content of a Processwire page on a Facebook page, triggered by saving the Processwire page.
      To set it up, configure the module with a Facebook app ID, secret and a Page ID. Following is additional configuration on Facebook for developers:
      Minimum Required Facebook App configuration:
      on Settings -> Basics, provide the App Domains, provide the Site URL, on Settings -> Advanced, set the API version (has been tested up to v3.3), add Product: Facebook Login, on Facebook Login -> Settings, set Client OAuth Login: Yes, set Web OAuth Login: Yes, set Enforce HTTPS: Yes, add "http://www.example.com/processwire/page/" to field Valid OAuth Redirect URIs. This module is configurable as follows:
      Templates: posts can take place only for pages with the defined templates. On/Off switch: specify a checkbox field that will not allow the post if checked. Specify a message and/or an image for the post.
      Usage
      edit the desired PW page and save; it will post right after the initial Facebook log in and permission granting. After that, an access token is kept.
       
      Download
      PW module directory: http://modules.processwire.com/modules/auto-fb-post/ Github: https://github.com/kastrind/AutoFbPost   Note: Facebook SDK for PHP is utilized.


×
×
  • Create New...