kongondo

Module: RuntimeMarkup Fieldtype & Inputfield

Recommended Posts

FieldtypeRuntimeMarkup and InputfieldRuntimeMarkup
 
Modules Directory: http://modules.processwire.com/modules/fieldtype-runtime-markup/
GitHub: https://github.com/kongondo/FieldtypeRuntimeMarkup
 
This module allows for custom markup to be dynamically (PHP) generated and output within a page's edit screen (in Admin).
 
The value for the fieldtype is generated at runtime. No data is saved in the database. The accompanying InputfieldRuntimeMarkup is only used to render/display the markup in the page edit screen.
 
The field's value is accessible from the ProcessWire API in the frontend like any other field, i.e. it has access to $page and $pages.
 
The module was commissioned/sponsored by @Valan. Although there's certainly other ways to achieve what this module does, it offers a dynamic and flexible alternative to generating your own markup in a page's edit screen whilst also allowing access to that markup in the frontend. Thanks Valan!
 
Warning/Consideration

  • Although access to ProcessWire's Fields' admin pages is only available to Superusers, this Fieldtype will evaluate and run the custom PHP Code entered and saved in the field's settings (Details tab). Utmost care should therefore be taken in making sure your code does not perform any CRUD operations!! (unless of course that's intentional)
  • The value for this fieldtype is generated at runtime and thus no data is stored in the database. This means that you cannot directly query a RuntimeMarkup field from $pages->find().

Usage and API

 
Backend

Enter your custom PHP snippet in the Details tab of your field (it is RECOMMENDED though that you use wireRenderFile() instead. See example below). Your code can be as simple or as complicated as you want as long as in the end you return a value that is not an array or an object or anything other than a string/integer.
 
FieldtypeRuntimeMarkup has access to $page (the current page being edited/viewed) and $pages. 
 
A very simple example.

return 'Hello';

Simple example.

return $page->title;

Simple example with markup.

return '<h2>' . $page->title . '</h2>';

Another simple example with markup.

$out = '<h1>hello ';
$out .= $page->title;
$out .= '</h1>';
return $out;

A more advanced example.

$p = $pages->get('/about-us/')->child('sort=random');
return '<p>' . $p->title . '</p>';

An even more complex example.

$str ='';
if($page->name == 'about-us') {
  $p = $page->children->last();
  $str = "<h2><a href='{$p->url}'>{$p->title}</a></h2>";
}

else {
  $str = "<h2><a href='{$page->url}'>{$page->title}</a></h2>";
}

return $str;

Rather than type your code directly in the Details tab of the field, it is highly recommended that you placed all your code in an external file and call that file using the core wireRenderFile() method. Taking this approach means you will be able to edit your code in your favourite text editor. It also means you will be able to type more text without having to scroll. Editing the file is also easier than editing the field. To use this approach, simply do:

return wireRenderFile('name-of-file');// file will be in /site/templates/

If using ProcessWire 3.x, you will need to use namespace as follows:

return ProcessWire\wireRenderFile('name-of-file');

How to access the value of RuntimeMarkup in the frontend (our field is called 'runtime_markup')
 
Access the field on the current page (just like any other field)

echo $page->runtime_markup;

Access the field on another page

echo $pages->get('/about-us/')->runtime_markup;

Screenshots
 
Backend
 
screenshot1.png
 
screenshot2.png
 
Frontend
 
screenshot3.png

  • Like 23
  • Thanks 1

Share this post


Link to post
Share on other sites

I think I understand what this module does but I'm having trouble grasping the situations in which it would be useful based on the examples you've given.

Is it just a convenience thing, so the editor doesn't have to look elsewhere for some information that might affect the content they decide to add to the page?

Share this post


Link to post
Share on other sites

There are many usefull situations like:

1. If you have a page for settings or tools with general entries/items and you use them on other pages like in a contactform you use the email field from the /settings/ page you could show this general fields on several places/templates

2. more advanced example could be to render statistic like content from subpages - imagine if you have a ad system that is counting views and clicks you could render a little stat with some html and some css/js at the rootpage of the ad's...

3. special for overview pages/rootpages it provides options to put some extra information/logic in such pages without the use of pagetable or something other complex..

4....

you get the idea

regards mr-fan

  • Like 3

Share this post


Link to post
Share on other sites

Simple answer is that @Valan had a need and commissioned me to develop this :biggrin: . 

Seriously though, mr-fan already covered it brilliantly. When I get some time, I'll post some other examples.

  • Like 2

Share this post


Link to post
Share on other sites

I have used a homemade solution to display information of related pages in the editor, which are needed to know how to handle the page (essentially user requests).

  • Like 2

Share this post


Link to post
Share on other sites

This is such a great module; recently I used it to create custom action buttons on my calendar/futuremail app;

Send or preview the email message for the future mail:

post-136-0-22253700-1443749172_thumb.png

send or preview a calendar event, which is typed by a chosen template (e.g. event, lesson reminder, etc.)

post-136-0-31179600-1443749173_thumb.png

  • Like 11

Share this post


Link to post
Share on other sites

Macrura - very cool - I hadn't thought of using it that way and will actually need similar buttons in an upcoming project so might just consider using this module to do it!

The trouble I am having with PW lately is that there are so many great new ways of doing things and it's hard to keep track of them all :)

  • Like 3

Share this post


Link to post
Share on other sites

In my case i only have 1 field and then my code checks for which template it's on, then outputs various buttons and messages; the buttons themselves just link to templates that read the url parameters and run some process. Eventually i'll probably have a generic module to process the buttons..

i think I'm going to be using this a lot!

  • Like 3

Share this post


Link to post
Share on other sites

Thank you Kongondo & @Valan for this great little helper!

For me as a non real dev...it is much more easy to get some special admin magic working with this!

This is one of the real big things i like with PW - there are tools that helps and can used by non experienced PHP users without to force them to do risky things within the backend...in other systems the level of complexity always grows and grows...with PW it seems it always get easier ;)

I'm on a hard deadline this days so less time to contribute but this little snippet may helps others - easy to use and very helpful.

It works as a kind of shortcut navigation to prev next siblings - like Kongondo showed off in his video to the notorious V.P.S.

I saw the raw links and thought hey i've a version of this running with UI buttons so here we go:

$out ='';
$siblings = $page->siblings;
//generate next & prev links output
if (count($siblings)) {
	$prev = $siblings->getPrev($page);
	if ($prev) {	
		$out .= '<a href="'.$prev->editUrl.'">';
		$out .= '<button type="button" name="button" class="ui-button ui-widget ui-corner-all ui-state-default">';
		$out .= '<span class="ui-button-text"><i class="fa fa-angle-double-left"></i> '.$prev->title.'</span></button>';
		$out .= '</a>';
	}
	$next = $siblings->getNext($page);
	if ($next) {
		$out .= '<a href="'.$next->editUrl.'">';
		$out .= '<button type="button" name="button" class="ui-button ui-widget ui-corner-all ui-state-default">';
		$out .= '<span class="ui-button-text">'.$next->title.' <i class="fa fa-angle-double-right"></i></span></button>';
		$out .= '</a>';
	}
if ($out <> "") $out = "<div class='NextPrevLinks'>".$out."</div>";
return "<div class='NextPrevLinks'>".$out."</div>";
}

Output of the field is:

post-2327-0-97972400-1443878534_thumb.jp

Have fun and best regards mr-fan

  • Like 4

Share this post


Link to post
Share on other sites

is it possible to use the value of this field for field dependency selectors? that would be really great but i didn't get it to work...

i created a field "testruntime"

post-2137-0-26897500-1445185352_thumb.pn

i set visibility for field "headline2"

post-2137-0-19718400-1445185351_thumb.pn

but the field does not show up...

post-2137-0-31086500-1445185353_thumb.pn

post-2137-0-84136000-1445185431_thumb.pn

any help for this? thanks for the great module - it was on my wishlist https://processwire.com/talk/topic/10555-using-pw-variables-in-descriptions-and-notes/   :)   ;)

edit: i was on the wrong track with this one... field dependencies work on the client side with JS and won't take care of the field value when the field is hidden

Share this post


Link to post
Share on other sites

Kongondo - just wanted to send a big thanks for this - just used it for the first time as a way to provide a preview of content from a hidden page tree and a modal edit link to edit that content - really very handy!

  • Like 1

Share this post


Link to post
Share on other sites

<silliness>I've been meaning to do a video demo of a list of silly thinks/pranks you can do with RunTimeMarkup...you know, a countdown to lunch break, a thing that shouts "peekaboo" every time you type a certain letter on your keyboard, a (not-so-silly) live spell-checker, etc....But then again, I have been meaning a lot of things... ;) </silliness>

  • Like 4

Share this post


Link to post
Share on other sites

That would surely convert many users from other CMSes - so please don't go that cinematic :)

  • Like 1

Share this post


Link to post
Share on other sites

Hi there?

is this possible?

if ($page->url=='/search/') {
  $title = $input->get['keyword']." ";
}
return $title;

I cannot return the value of $input->get['keyword'] even though it exist in the url?

Share this post


Link to post
Share on other sites

I'm not sure if you can access these items with the array notation, try $input->get('keyword') or $input->get->keyword.

Edit: And just as I thought, only $pages and $page are available as local variables. All the other api variables need to be accessed as $this->input or wire('input').

  • Like 2

Share this post


Link to post
Share on other sites

I'm not sure if you can access these items with the array notation, try $input->get('keyword') or $input->get->keyword.

Also did not work on url variables... i tried this but can't get to work...

Here's my url output

thefilipinodoctor/search/?keyword=Supranueron

Share this post


Link to post
Share on other sites

Also did not work on url variables... i tried this but can't get to work...

Speedy people here. Read my edited post above.

Share this post


Link to post
Share on other sites

@naldrocks98, 

Yes, @LostKobrakai is right about variable scope; RM only knows $page and $pages :-). So, this with your 'array notation', works:

$title = '';

if ($page->url=='/search/') {
  $title = $this->wire('input')->get['keyword'] ." ";
}
return $title;

If you had debug turned on, you could have seen the errors and fixed it :-). You also need to instantiate $title, otherwise, you will get an error for pages that don't match.

Edit

Btw, just curious, how are you using this?

Edited by kongondo

Share this post


Link to post
Share on other sites

Greatly useful module guys, thanks!

Just used it to provide a list of collected emails for simple copy/paste into send field

return $page->children->implode(', ', 'email');

Couldn't get any simpler than this!

PS: of course it would be great to have ACE on the code field like i Hanna Code ;)

  • Like 3

Share this post


Link to post
Share on other sites

PS: of course it would be great to have ACE on the code field like i Hanna Code ;)

The module could just check if Inputfield Ace Extended is installed and use it if so. That would prevent the big filesize like it's the case for hanna code and leave the code editor optional.

  • Like 3

Share this post


Link to post
Share on other sites

@kongondo - wondering if there might be an issue with renaming fields using this fieldtype;

i tried renaming an existing field but got a sql error;

Share this post


Link to post
Share on other sites

@Macrura,
 
Thanks for catching this. You will notice the same error if you tried to rename a FieldtypeConcat field. The error occurs because these Fieldtypes do not create a database table, i.e. there is no field_my_runtime_field table. MySQL throws the error since it can't find such a table on file, i.e. there is no field_my_runtime_field.frm file (every MySQL table is represented on disk by a .frm file that describes the table's format). It throws the error in Fields.php, in the __save() method, here. Although the method is hookable, I'll have a talk with Ryan to see what's the best way to handle this.

Edit: Forgot to provide a temporary solution:

As we know, the names of fields themselves are stored in the 'fields' table. As we wait to resolve this, we can always change a fields name there. Not ideal, I know, but we will get to the bottom of this.

Edit 2: Issue fixed in this commit in ProcessWire 2.7.2 (dev)

Edited by kongondo
  • Like 1

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 Lex Sanchez
      Video or Social Post Embed
      Based on the TextformatterVideoEmbed module developed by Ryan Cramer, we have added the possibility to embed publications of the main social networks Facebook, Twitter and Instagram.
      ProcessWire Textformatter module that enables translation of YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu URLs to full embed codes, resulting in a viewable video or social post in textarea fields you apply it to.
      How to install
      Download or Clone from Github: https://github.com/lexsanchez/VideoOrSocialPostEmbed
      Copy the VideoOrSocialPostEmbed.module file to your /site/modules/ directory (or place it in /site/modules/VideoOrSocialPostEmbed/).
      Click check for new modules in ProcessWire Admin Modules screen. Click install for the module labeled: "Video or Social Post Embed".
      Now you will be on the module config screen. Please make note of the config options and set as you see fit.
      How to use
      Edit your body field in Setup > Fields (or whatever field(s) you will be placing videos in). On the details tab, find the Text Formatters field and select "Video or Social Post Embed". Save.
      Edit a page using the field you edited and paste in YouTube, Vimeo, Facebook, Twitter, Instagram and/or Issuu URLs each on their own paragraph.
      Example
      How it might look in your editor (like TinyMCE):
      How it works
      This module uses YouTube, Vimeo, Instagram, Facebook, Twitter and Issuu oEmbed services to generate the embed codes populated in your content. After these services are queried the first time, the embed code is cached so that it doesn't need to be pulled again.
      Configuration
      You may want to update the max width and max height settings on the module's configuration screen. You should make these consistent with what is supported by your site design.
      If you change these max width / max height settings you may also want to check the box to clear cache, so that YouTube/Vimeo/Facebook/Twitter/Instagram/Issuu oembed services will generate new embed codes for you.
      Using with Markdown, Textile or other LML
      This text formatter is looking for a YouTube, Vimeo, Instagram, Facebook, Twitter or Issuu video URL surrounded by paragraph tags. As a result, if you are using Markdown or Textile (or something else like it) you want that text formatter to run before this one. That ensures that the expected paragraph tags will be present when VideoOrSocialPostEmbed runs. You can control the order that text formatters are run in by drag/drop sorting in the field editor.
      Copyright 2018 by Ryan Cramer / Updated by Lex Sanchez
    • By kixe
      Email Verification
      This module provides functions to validate email adresses and hosts. The module generates a textfile for blacklisted mailhosts (trashmail), which will be always up to date.
      Download
      https://modules.processwire.com/modules/email-verification/
      API
      // get module $mailcheck = $modules->get('EmailVerification'); // return bool/ string - automatted update of blacklist file $mailcheck->blacklisted(email|domain) // return bool - validate a top level domain, checks against IANA list $mailcheck->validTLD(tld) // return array of punycoded TLDs - cyclic updated, data pulled from IANA $mailcheck->getTLDs(cycle=2592000) // return bool - checks syntax converts to punycode $mailcheck->validDomainName(domain); // return bool - checks punycode encoded syntax $mailcheck->validHostName(host); // return bool - checks syntax and accessibility $mailcheck->validHost(email|domain) // add a single value to blacklist $mailcheck->addToBlacklist(email|domain) USAGE
      $mailcheck = $modules->get('EmailCheck'); $email = 'susi@trashmail.com'; if($mailcheck->blacklisted($email)) echo 'Email Provider not allowed'; if(!$mailcheck->validHost($email)) echo 'Mailhost not available'; Example blacklist file:  blacklist.txt
       
    • By teppo
      Code Blocks Textformatter is a tiny Textformatter module I cooked up to add support for code blocks to text/textarea/RTE fields on some of the sites I work with. Unlike a full-blown Markdown Textformatter – which is something that we already have in the core – this module simply adds support for fenced and inline code blocks.
      The syntax is based on the GitHub code block documentation, so please refer to that for additional instructions. The README at GitHub also includes some basic examples. As with any Textformatter, in order to enable this one, install it and enable it via field settings. Note that there's no syntax highlighting built in (at least for the time being), so use a tool of your choice for that – personally I prefer Prism.js.
      Since this module doesn't use a Markdown tool behind the scenes, but rather some home baked regular expressions, there's always the possibility that I've missed something – but please let me know if you use this module and run into any issues. On the other hand this module should be relatively fast and unobtrusive, as there are no unnecessary bits of code to run 
      GitHub repository: https://github.com/teppokoivula/TextformatterCodeBlocks Modules directory: http://modules.processwire.com/modules/textformatter-code-blocks/
    • By theo
      Here is my first processwire module (beta).
      https://github.com/theo222/ImagePickerField
      A lot of "first times". First time Github, Markdown and of course PW Modules.
      So be gentle please.
      I hope it works.