justb3a

Module: Image Extra

Recommended Posts

10 hours ago, justb3a said:

One opportunity would be to use a `label` element if it isn't a multilingual site and a `strong` tag if it is one.  What do you think?

Sounds good, thanks.

10 hours ago, justb3a said:

The idea behind this was that some textformatter like "NewLineToBreak" or "NewLineToListItem" doesn't make that much sense applied to an one liner input element.

True, but the textformatter that I'm thinking of is HTML Entity Encoder, which is important for any text field to avoid ambiguous ampersands or other invalid HTML. The string could be manually encoded in the template but more convenient to set-and-forget with a textformatter. :)

Share this post


Link to post
Share on other sites

Hi,

Thanks so much - that makes sense... I've tried to combine the below in a lot of different ways but keep getting an error...

Any ideas?

Thanks

<?php
if ($image->caption){
    //Output markup 1
}
else {
    //Output markup 2
}
?>

<?foreach($page->images as $image) {
 $thumb = $image->width(1040); 
echo "<li><img src='$thumb->url' alt='$image->description'><p class='caption'><strong>{$image->imagetitle}</strong> <em>{$image->imagetext}</em> <span><br>{$image->role}</span></p></li>";}
?>

 

Edited by kongondo
Mod Note: Moved your question to this module's support forum

Share this post


Link to post
Share on other sites

hi!
thanks for this great module!

today I experienced a strange issue when using this module with the Video Fieldtype Module
I get the following error when uploading a video, when the image extra module is installed:

<br />
<b>Notice</b>:  Trying to get property of non-object in <b>/www/htdocs/w00dd152/projekte/jp-relaunch/site/modules/ImageExtra/ImageExtra.module</b> on line <b>722</b><br />
[{"error":false,"message":"Added file: portfolio_screencap_02.mp4","file":"\/jp-relaunch\/site\/assets\/files\/1162\/portfolio_screencap_02.mp4","size":3214711,"markup":"<li id='file_c17b44756649023a42ba014c5b29202c' class='InputfieldFile InputfieldImage InputfieldVideo ui-widget'>\n\t\t<p class='InputfieldFileInfo ui-widget ui-widget-header'>\n\t\t\t<span class='ui-icon ui-icon-arrowthick-2-n-s'><\/span>\n\t\t\t<span class='InputfieldFileName'>portfolio_screencap_02.mp4<\/span> \n\t\t\t<span class='InputfieldFileStats'>• 3,139 kB • <\/span> \n\t\t\t<label class='InputfieldFileDelete'><input type='checkbox' name='delete_video_repeater1162_c17b44756649023a42ba014c5b29202c' value='1' \/><span class='ui-icon ui-icon-trash'>Delete<\/span><\/label>\n\t\t\t<a class='InputfieldFileMove InputfieldFileMoveBottom' href='#'><span class='ui-icon ui-icon-arrowthickstop-1-s'><\/span><\/a> \n\t\t\t<a class='InputfieldFileMove InputfieldFileMoveTop' href='#'><span class='ui-icon ui-icon-arrowthickstop-1-n'><\/span><\/a> \n\t\t<\/p>\n\t\t\t<div class='InputfieldFileDescription'><label for='description_video_repeater1162_c17b44756649023a42ba014c5b29202c' class='detail'>Description<\/label><input type='text' name='description_video_repeater1162_c17b44756649023a42ba014c5b29202c' id='description_video_repeater1162_c17b44756649023a42ba014c5b29202c' value='' \/><\/div>\n\t\t<br \/><label class='InputfieldFileDescription'><span class='detail'>Subtitles<\/span>\n\t\t<br \/><br \/>In templates, you can access this subtitles file (portfolio_screencap_02.srt) using: <code>$page->video->eq(0)->subtitles<\/code><br \/>In templates you can access a formatted transcript (converted from subtitles entered in SRT format), by using: <code>$page->video->eq(0)->transcript<\/code>\n\t\t<br \/><br \/><textarea rows='10' name='subtitles_video_repeater1162_c17b44756649023a42ba014c5b29202c' \/><\/textarea>\n\t\t\t<input class='InputfieldFileSort' type='text' name='sort_video_repeater1162_c17b44756649023a42ba014c5b29202c' value='0' \/>\n\t\t<\/p><\/li>","replace":false,"overwrite":0}]

I testes this in PW 3.0 with the newest versions of both modules installed.
Not sure why its even interfering with the video field..
When I disable the image extra module, everything works fine.

Share this post


Link to post
Share on other sites

@jploch - I'd like to see a dump of $event after line 718 because $field is not an object and it should be.

That said, a quick fix might be to change the hook on line 97 to:

InputfieldImage::processInputFile

 

  • Like 1

Share this post


Link to post
Share on other sites
20 hours ago, adrian said:

@jploch - I'd like to see a dump of $event after line 718 because $field is not an object and it should be.

That said, a quick fix might be to change the hook on line 97 to:


InputfieldImage::processInputFile

 

Thx! this fixed it for me

  • Like 1

Share this post


Link to post
Share on other sites

@Jon E 

Just use the comparison inside the foreach loop:

foreach ($page->images as $image) {
  $caption = '';
  if ($image->imagetitle) {
    $caption = "<p class='caption'>{$image->imagetitle}</p>";
  }

  echo "<li><img src='{$image->width(1040)->url}' alt='{$image->description}'>$caption</li>";
}

Or if you want to combine multiple parts: you can check every extra field individually and concatenate the caption before outputting it.

foreach ($page->images as $image) {
  $caption = '';
  if ($image->imagetitle) $caption .= "<strong>{$image->imagetitle}</strong>";
  if ($image->imagetext) $caption .= "<em>{$image->imagetext}</em>";
  if ($image->role) $caption .= "<span>{$image->role}</span>";
  if ($caption) $caption = "<p class='caption'>$caption</p>";

  echo "<li><img src='{$image->width(1040)->url}' alt='{$image->description}'>$caption</li>";
}

 

  • Like 1

Share this post


Link to post
Share on other sites

Hi there! And, as always, thanks for a perfect product!

Would like to discuss an interesting case. Let's suppose we have some images attached to different pages, each image having some extra fields including uid field which is unique. We have to build an api page which should receive requests like /api?uid=efv97yg and it should return some JSON about the image with that uid.

Is there any possibility to find an image by its extrafield value (e.g. uid)? Well, i know that we can do something like this:

$pages_ = $pages->find('template=page_with_fotos');
foreach($pages_ as $page_)
	{
	$images = $page_->images;
	foreach($images as $image)
		{
		if($image->uid !== $uid) continue;
		$json = json_encode($image);
		break;
		}
	}
echo $json;

But its not very elegant.

And even worse:

$sql = "select * from field_foto where uid=$uid";
$query = $database->prepare($sql);
$query->execute();
...

What is on my wishlist:

//pseudocode, will NOT work for sure!

$foto = $field_fotos->get("uid=$uid");
...

Will appreciate any advice. Thanks!

Share this post


Link to post
Share on other sites

Just used this module for adding a video link to images. There was a glitch that there was no indication on the thumbnails whether there is a link added or not, so I put together a small js/css combo to add an icon:

has-video.thumb.gif.6e88144313e59ece60e44535eb9dda44.gif

Here is the corresponding code - dirty but works :)

Spoiler

var fieldname = 'video_url_project_images';

function updateVideoItems() {

    $('.gridImage__hover.has-video').removeClass('has-video');

    $('input[id*="video_url_project_images"][value!=""]').each(function() {

        var $item = $(this),
            seekId = $item.attr('id').replace(fieldname, 'file'),
            $target = $('#' + seekId);

        if($target.length) {
            $target.find('.gridImage__hover').addClass('has-video');
        }
    });
}

$(document).ready(function() {
    updateVideoItems();
});

$(document).on('keyup change', 'input[id*="' + fieldname + '"]', function() {
    updateVideoItems();
});

.gridImage__hover.has-video .gridImage__inner::after {
    content: "";
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 30px;
    height: 30px;
    background: #333 url('/site/templates/images/icons/play-circle.svg') center center no-repeat;
    background-size: 30px;
    border-radius: 100%;
    border: 2px solid white;
    background-clip: content-box;
}

 

 

  • Like 1

Share this post


Link to post
Share on other sites

There are two different ways to get the label of any input Field:

echo "This is the field label: {$page->fields->get("simple_slider")->label}";
echo "This is the field label: {$page->fields->get("simple_slider")->getLabel()}";

Let's pretend I added to my image field an extra field "location" with the label "This was in:". So if I want the value of the "location" field I do it like this:

echo "This is was in: {$page->simple_slider->location}";
// Outputs "Barcelona"

How can I get the LABEL of the location field?

Something like:

// not working code:
echo "{$page->fields->get("simple_slider")->location->getLabel()}: {$page->simple_slider->location}";
// Should output "This was in: Barcelona"

 

Share this post


Link to post
Share on other sites

Hi,

since extra fields aren't regular ProcessWire fields you cannot access the labels using `->getLabel()` method or `->label` property.
The extra field labels are saved in the regarding field settings (table fields, column data) using json and looks like this:

{"otherFieldSettings":"{\"cf_label\":{\"cf_label__location\":\"Location\",\"cf_label__location__1012\":\"Ort\",\"cf_label__custom__1013\":\"Paikka\"}}"}

You can get the label using this functionality:

$fieldSettings = $fields->get('images')->otherFieldSettings;
$settings = json_decode($fieldSettings);
echo $settings->cf_label->cf_label__location;

As you can see there is no error handling or fallback strategy. Therefore I updated the module and added a method called getExtraLabel()

Usage example:

// outputs something like: "Location: Munich"
echo $image->getExtraLabel('location') . ': ' . $image->location;

// outputs something like: "Ort: München"
echo $image->getExtraLabel('location', 'de') . ': ' . $image->location;


 

  • Like 3

Share this post


Link to post
Share on other sites

just tested with 3.0.65 and it seems that the pagelink field is not working?

imageextra.thumb.jpg.9ee7b8bd45060a8c970cea78bb8f1388.jpg

Best regards mr-fan

Share this post


Link to post
Share on other sites

Thanks @mr-fan: there was a little bug figuring out, whether the user is working in the backend or not (differentiate between int(0) und false :D ). The belonging JavaScript file wasn't loaded.

  • Like 1

Share this post


Link to post
Share on other sites

Thank you for this great module and for fixing so fast...often when it come to the javascript debuging i'm a little lost...;)

best regards mr-fan

Share this post


Link to post
Share on other sites

Thank you for the module!

I'm using it to add a Markdown enhanced captions for some blog images. I have a problem - the text is processed by the Mardown module only for the first image (in ProcessWire 3.0.72 multi language).
Could someone give me a hint about where to look, please? I'm stumped.
I'm retrieving them like this:

<?php foreach (pages('parent=8888') as $item) { ?>

    <div>
        <div class="uk-card uk-card-default">

            <?php if (count($item->images)) {
                      $item_image = $item->images->getRandom(); ?>

                <div class="uk-card-media-top">
                    <figure>
                        <img src="<?=$item_image->size(580, 384, ['quality' => 75])->url?>"
                             title="<?=$item_image->description?>"
                             alt="<?=$item_image->description?>">
                        <figcaption class="uk-text-meta uk-padding uk-padding-remove-vertical"><?=$item_image->caption?></figcaption>
                    </figure>
                </div>

            <?php } ?>

            <div class="uk-card-body">
                <h3 class="uk-card-title"><a href="<?=$item->url?>" title=""><?=$item->title?></a></h3>
                <p><?=$item->summary?></p>
            </div>
        </div>
    </div>

<?php } ?>

2017-08-21_150736.png

Share this post


Link to post
Share on other sites

OK, found the culprit, is the static variable

$alreadyFormatted

which is set to true at line 527 (module version 106):

525  public function formatExtraValue(HookEvent $event) {
526    if (!self::$alreadyFormatted) {
527      self::$alreadyFormatted = true;

I don't know its purpose, but in my case (a loop retrieving captions for an image from every blog post) it stops the text formatter from processing any item after the first one. So I commented it out, I'll see if anything goes wrong.

Share this post


Link to post
Share on other sites

@geedamed I took me some time but I figured out, what the problem might be. I found a fix, but I do not understand exactly why this is happening. So if anybody could explain this behaviour, feel free to share it :)

 I added the `already formatted` check because in some cases the formatter was called twice (which could break the output). Let's define `in some cases`:

  • images are outputted on the same page as saved to
  • it just counts for the first/one image field

I compared the passed HookEvents. The only difference was that in the first argument, which contains the current Page object, the page title was missing.
So I added a check whether the Page object does contain a title, otherwise skip the formatter. I tested different cases (multiple images, multiple image fields, output from another page and so on). Seems to work – or every extra field the formatter is only called once. 

Share this post


Link to post
Share on other sites

Hi @justb3a I just found your module and I was wondering if you could add a cropping option field with all of it's values: northwest, north, northeast, west, center, east, southwest, south, southeast.

Share this post


Link to post
Share on other sites

Very useful Module.

Is there a way to hide / unpublish a single image temporarily instead of deleting (trashing) the entire image + information?

A checkbox for this would be great.

Thank you.

Share this post


Link to post
Share on other sites
On 03/09/2017 at 11:43 PM, PWaddict said:

Hi @justb3a I just found your module and I was wondering if you could add a cropping option field with all of it's values: northwest, north, northeast, west, center, east, southwest, south, southeast.

@PWaddict: There is already a module for cropping images: CroppableImage3

On 04/09/2017 at 10:29 PM, theo said:

Very useful Module.

Is there a way to hide / unpublish a single image temporarily instead of deleting (trashing) the entire image + information?

A checkbox for this would be great.

Thank you.

@theo: Actually the core/module do support it in a way that's not immediately obvious or as straightforward as checking a checkbox, but it's still quite useful and worthwhile when you need the capability. You could use tags or any other image extra field to achieve this. 

  1. Edit any existing files/images field, or create a new one.

  2. When editing the field settings,  check the box to enable “tags”, or create a new extra field named “hidden“ or something like that.

  3. In the “tags” or “hidden“ field for the image (which should be unpublished), enter a specific phrase like “hidden" (tags field)  or “1“ (hidden field).

  4. Now you need to check if the file should be shown on the front-end of your site. Here's how you do that:

// tag usage example
if (!$image->hasTag('hidden')) echo "<img src='$image->url' alt=''>";

// extra field hidden example
if (!$image->hidden) echo "<img src='$image->url' alt=''>";

 

You could also send a feature request to add this as a core feature (so you do not need to check manually whether the image is hidden and as an extra bonus the hidden images would be visible at first glance using opacity to indicate that).

  • Like 1

Share this post


Link to post
Share on other sites

seem to be getting a number "1" added to the first custom field for some reason.

59d3bbcce690a_Screenshot2017-10-0317_31_24.thumb.png.c6f7c7fb138555d259877d812c706cd3.png

Share this post


Link to post
Share on other sites

I'm having an issue with the module. When I add an additional field to an existing image field and try to edit the page I get an error like:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_headerImage.title' in 'field list'

I get a similar but more verbose error on the frontend trying to view the page.

Removing the additional field resumes normal behaviour for the page.

I have other fields that I've added a title field to that work fine, so it's worked in the past, and image fields that already have custom fields have no problem, but I can't add more.

I'm working with the latest build of PW (3.0.79)

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 kongondo
      Process Sites Manager
      ProcessWire supports multiple site setups using various methods. One of the more common approaches is running multiple sites from the same core installation with each site maintaining its own database (aka option #1). This approach requires the site admin to initially install ProcessWire in a temporary directory for each new site. The directory then needs to be renamed as site-xxx, where ‘xxx’ is any name you want to use to differentiate the installation from other sites, before it is moved to the webroot. For instance, site-mysite, site-another, site-whatever. In addition, the /wire/index.config.php file must be copied/moved to the webroot. Each time a site is added, the index.config.php has to be edited to add ‘domain’ => ‘site-directory’ key=>value pairs for the site. This process can become a bit tedious. This module aims to automate the whole process.
       
      The module is based off the official ProcessWire installer. Creating a site is as simple as completing and submitting a single form! The module will:
      Install a ProcessWire site in your named directory, applying chmod values as specified
      Move the directory to your webroot
      Update/Create a Superuser account as per the submitted form, including setting the desired admin theme and colour
      Update sites.json (used by index.config.php to get array of installed sites)
       
      Please note that this module is not a multiple sites solution! It is just a helper class for those using option #1. Your multi-sites solution will still be delivered by ProcessWire core. The only difference is index.config.php is slightly different from the one that ships with ProcessWire.
      ALPHA SOFTWARE!
      This module works as expected. However, it needs a bit more testing in different environments. In light of this, it is labelled as alpha and should not be used in a production environment.
      Download from GitHub: Sites Manager
      Features
      Install unlimited number of sites in one ProcessWire install
      Choose an Admin Theme to auto-install along with the site installation
      Install and maintain site profiles for reuse to create other sites
      Client and server-side validation of site creation form
      Edit uploaded profiles (e.g., replace profile file)
      Lock installed sites and profiles to prevent editing
      Bulk delete site profiles, installed site directories and/or databases (confirmation required for latter two)
      View important site details (admin login, chmod, etc)
      Links to installed sites home and admin pages
      Timezones auto-complete/-suggest
      Installation
      Pre-requisites
      Domains
      Installations’ domains/sub-domains must exist before installing the site. This is needed in order to update/save the Superuser account for the new site. For instance, if creating a site with the subdomain blog.mydomain.com (with directory site-blog), that subdomain must be active. For local development, if using Apache, for instance, a virtual host directive for blog.mydomain.com must have been set up prior to the installation. For remote/live sites, the subdomain must have been set up at your Domain Name Registrar.
      Site Profiles
      You will need to prepare site profiles for use with the module. Example site profiles ship with ProcessWire. These include ‘site-default’, ‘site-classic’, ‘site-blank’, etc. The module only accepts zip files. Each of these folders needs to be compressed into a zip file, for instance ‘site-default.zip’, ‘site-languages.zip’, etc. Please note that the other content you get with ProcessWire downloads are not required. These include the wire folder and .gitignore, index.php, etc files. Do not include any of these in the ‘site-whatever.zip’.
      You are not limited to using the site profiles that ship with ProcessWire. You can create and use your own custom profiles as long as they are structured according to the format ProcessWire expects (@see site-default that ships with ProcessWire as an example).
      Install
      Install the module like any other. It will create required templates, fields and pages (hidden in admin under Multi Sites). The install will also copy two files to your webroot; sites.json and index.config.php. If any identical module components (field, templates, files, etc) are found in your system, the module will not install but will instead error out with a relevant message.
      Module Files
      The two file sites.json and index.config.php should not be removed from your webroot if you are using this module. The former should remain writable at all times. The index.config.php is a modified version of the one that ships with ProcessWire. Rather than editing the file directly with new entries for installed sites, it fetches the information about multi-sites sites that ProcessWire needs to serve directly from the site.json contents which it converts to an array before passing off to ProcessWire. We haven’t done any real-world testing (yet) but have not observed any noticeable delays in serving the multi-sites sites in this manner.
      Usage
      The module will be useful in both development and production (@see note above! When ready) environments.
      For development work, there are times when you need to quickly put up a temporary site to test something, debug an install or create a mock website to present draft ideas to a client, etc. This module allows you to do all these, and more, easily and quickly.
      For live sites, the module can be a time saver, allowing you to install and manage (very limited feature-set at present) your sites from one dashboard.
      Site Profiles
      The first thing to do after installing the module is to upload at least one site profile. In the Upload page, complete the ‘upload a site profile form’. Give the profile upload a title, optionally a description (good reminder about what the profile features), ProcessWire compatibility and of course the profile zip file itself. Profile uploads are saved as hidden pages in the admin. This enables reuse of the profile, so that you don’t have to upload it over and over every time you need to install a site.
      Uploaded profiles are listed under the page Profiles. Head over there to see a list of available profiles. Using this page, you can edit individual profiles, e.g. change the title or replace the profile zip file. You can also lock/unlock or delete profiles. You are now ready to create sites.
      Create/Install Sites
      Head over to the Create page. This is where the automation really happens. Complete the form as required. Most of the inputs/fields should be familiar if you’ve ever installed ProcessWire. All fields, except for Description and HTTP Host Names, must be completed. It is recommended to complete these as well. Each field is accompanied by an explanation about what what it does (straight off the ProcessWire install you are used to). One bonus you get is you are able to select both an Admin Theme and Colour Theme to install! If you like AdminThemeReno in Blue, for instance, you can have that installed for you. Another bonus is the Default Timezone field. It uses auto-complete so that you don’t have to type the whole timezone name. Please note that, unlike in the official installer, profile previews are not (currently?) available.
      When you are happy with your settings click save to start the install. Please note that due to the additional client-side validation, if any of the checks fail, the errors to correct will be displayed in a modal and the form will not be submitted. Checks include mismatched Superuser passwords, empty required fields, invalid emails, short admin login URL/name, etc.
      If all went well, the site should install! Please note that currently (and a tad annoyingly!), the install will abort (sometimes half-way), if it hits an error. This has nothing to do with the official ProcessWire install but the checks we have put in the module code, currently. Hopefully, with feedback from the community, we can change how the module deals with errors. Most errors, if they appear, will be related to the file system...cannot write to file blah blah, etc.
      If you clicked on the button Save & View Sites, you should, momentarily (it may take a while depending on your system), see your new site on the page Installed. Otherwise, navigate to that page.
      Installed
      On this page you see a list of installed sites and information about them. To view your site, click on the link in Domain. The site opens in a new tab. To head straight to the admin, click on the link in Admin Login. Log in with the Superuser credentials you supplied on the ‘create site form’. Voilà! Your new site’s admin with the theme and colours your selected applied for the Superuser!
      On the Installed sites page, you can lock/unlock the installed sites records (the pages). You can also bulk delete the sites’ directories (the site-mydomain directories in webroot) and/or their databases. A dialog appears asking you to confirm these latter two actions. Be careful with these! They are useful for erasing temporary test sites but you need to double check your intended action. It is therefore advisable to lock sites to prevent unintended erasure.
      Deleting a site’s directory and/or database also deletes its associated page record. This means you won’t be able to view it in the Installed page.
      Cleanup
      Use this to make a clean getaway before uninstalling the module. The page will also allow you to specify whether you wish to delete the sites.json and index.config.php files from your webroot.
      Technicalities/Issues
      Only Superusers can use the module.
      ProcessWire 2.7 - 3.x compatible
      Currently using ProcessWire 2.7 installer (install.php)
      Potential race condition when sites.json is being updated on a new site install vs. index.config.php accessing the json file?
      Not tested with sub-directory installs (for instance localhost/pw/my-site-here/)
      Currently not doing the extra/experimental database stuff (database charset and engine)
      Future Possibilities
      Install specified modules along with the ProcessWire install
      Create installation profiles and/or allow JSON/CSV install configurations (useful for repetitive values, e.g. where Superuser email doesn’t change)
      Profile previews?
      Credits
      @ryan: for the ProcessWire installer
      @abdus: for the index.config.php reading from JSON idea
      @swampmusic: for the challenge
      Testing
      Please help test and report any issues. Feature suggestions are also welcome. Comments on anything from UX to technical stuff to make this as robust as possible are appreciated.
      Video Demo
      Quick Demo (excuse the video quality please )
      Screens
       

    • By Robin S
      Some introduction...
      This module is experimental and there are probably bugs - so treat it as alpha and don't use it on production websites.
      I started on this module because there have been quite a few requests for "fake" or "invisible" parent functionality and I was curious about what is possible given that the idea sort of goes against the PW page structure philosophy. I'm not sure that I will use this module myself, just because I don't really see a long list of pages under Home (or anywhere else) as untidy or cluttered. I would tend to use Lister Pro when I want to see some set of pages as a self-contained group. But maybe others will find it useful.
      At the moment this module does not manipulate the breadcrumb menu in admin. So when you are editing or adding a virtual child the real location of the page is revealed in the breadcrumb menu. That's because I don't see the point in trying to comprehensively fool users about the real location of pages - I think it's better that they have some understanding of where the pages really are. But I'm open to feedback on this and it is possible to alter the breadcrumbs if there's a consensus that it would be better that way.
       
      Virtual Parents
      Allows pages in Page List to be grouped under a virtual parent.
      This module manipulates the page list and the flyout tree menu to make it appear that one or more pages are children of another page when in fact they are siblings of that page.
      Why would you do that instead of actually putting the child pages inside the parent? Mainly if you want to avoid adding the parent name as part of the URL. For example, suppose you have some pages that you want to be accessed at URLs directly off the site root: yourdomain.com/some-page/. But in the page list you want them to be appear under a parent for the sake of visual grouping or to declutter the page list under Home.
      Example of how the page structure actually is

      Example of how the page structure appears with Virtual Parents activated

      How it works
      This module identifies the virtual parents and virtual children by way of template. You define a single template as the virtual parent template and one or more templates as the virtual child templates. Anytime pages using the child template(s) are siblings of a page using the parent template, those child pages will appear as children of the virtual parent in the page list and tree menu.
      You will want to create dedicated templates for identifying virtual parents and virtual children and reserve them just for use with this module.
      Features
      Adjusts both page list and tree flyout menu to show the virtual parent/child structure, including the count of child pages. Works everywhere page list is used: Page List Select / Page List Select Multiple (and therefore CKEditor link dialog). Intercepts the "Add page" process in admin, so that when an attempt is made to add a child to a virtual parent, the child is added where it belongs (the next level up) and the template selection is limited to virtual child templates. Intercepts moving and sorting pages in the page list, to ensure only virtual children may be moved/sorted under the virtual parent. Superusers have a toggle switch at the bottom of the page list to easily disable/enable Virtual Parents in order to get a view of what the real page structure is. Usage
      Install the Virtual Parents module.
      In the module config, enter pairs of parent/child template names in the form virtual_parent_template=virtual_child_template. If needed you can specify multiple pipe-separated child templates: virtual_parent_template=child_template_1|child_template_2. One pair of template names per line.
      There is a checkbox in the module config to toggle Virtual Pages on and off, but it's more convenient to use this from the page list.
      Notes
      It's important to keep in mind the real location of the virtual child pages. This module is only concerned with adjusting the appearance of page list and tree menu for the sake of visual grouping and tidiness. In all other respects the virtual children are not children of the virtual parent at all.
      It's recommended to select an icon for the virtual parent template (Advanced tab) so virtual parents are marked out in the page list as being different from normal parent pages.
      Do not place real children under a virtual parent. There is some protection against this when moving pages in the page list, but when it comes to changing a page's parent via the Settings tab the only protection is common sense.
       
      https://github.com/Toutouwai/VirtualParents
    • By horst
      Wire Mail SMTP

      An extension to the new WireMail base class that uses SMTP-transport

      This module integrates EmailMessage, SMTP and SASL php-libraries from Manuel Lemos into ProcessWire. I use this continously evolved libraries for about 10 years now and there was never a reason or occasion not to do so. I use it nearly every day in my office for automated composing and sending personalized messages with attachments, requests for Disposition Notifications, etc. Also I have used it for sending personalized Bulkmails many times.

      The WireMailSmtp module extends the new email-related WireMail base class introduced in ProcessWire 2.4.1 (while this writing, the dev-branch only).
       
      Here are Ryans announcement.



      Current Version 0.2.7
      get it from the Modules Directory Install and Configure

      Download the module into your site/modules/ directory and install it.

      In the config page you fill in settings for the SMTP server and optionaly the (default) sender, like email address, name and signature.
      You can test the smtp settings directly there. If it says "SUCCESS! SMTP settings appear to work correctly." you are ready to start using it in templates, modules or bootstrap scripts.


      Usage Examples
      The simplest way to use it:
      $numSent = wireMail($to, $from, $subject, $textBody); $numSent = wireMail($to, '', $subject, $textBody); // or with a default sender emailaddress on config page This will send a plain text message to each recipient.
       
      You may also use the object oriented style:
      $mail = wireMail(); // calling an empty wireMail() returns a wireMail object $mail->to($toEmail, $toName); $mail->from = $yourEmailaddress; // if you don't have set a default sender in config // or if you want to override that $mail->subject($subject); $mail->body($textBody); $numSent = $mail->send(); Or chained, like everywhere in ProcessWire:
      $mail = wireMail(); $numSent = $mail->to($toEmail)->subject($subject)->body($textBody)->send(); Additionaly to the basics there are more options available with WireMailSmtp. The main difference compared to the WireMail BaseClass is the sendSingle option. With it you can set only one To-Recipient but additional CC-Recipients.
      $mail = wireMail(); $mail->sendSingle(true)->to($toEmail, $toName)->cc(array('person1@example.com', 'person2@example.com', 'person3@example.com')); $numSent = $mail->subject($subject)->body($textBody)->send(); The same as function call with options array:
      $options = array( 'sendSingle' => true, 'cc' => array('person1@example.com', 'person2@example.com', 'person3@example.com') ); $numSent = wireMail($to, '', $subject, $textBody, $options); There are methods to your disposal to check if you have the right WireMail-Class and if the SMTP-settings are working:
      $mail = wireMail(); if($mail->className != 'WireMailSmtp') { // Uups, wrong WireMail-Class: do something to inform the user and quit echo "<p>Couldn't get the right WireMail-Module (WireMailSmtp). found: {$mail->className}</p>"; return; } if(!$mail->testConnection()) { // Connection not working: echo "<p>Couldn't connect to the SMTP server. Please check the {$mail->className} modules config settings!</p>"; return; } Following are a ...


      List of all options and features


      testConnection () - returns true on success, false on failures


      sendSingle ( true | false ) - default is false

      sendBulk ( true | false ) - default is false, Set this to true if you have lots of recipients (50+)


      to ($recipients) - one emailaddress or array with multiple emailaddresses

      cc ($recipients) - only available with mode sendSingle, one emailaddress or array with multiple emailaddresses

      bcc ($recipients) - one emailaddress or array with multiple emailaddresses

       
      from = 'person@example.com' - emailaddress, can be set in module config (called Sender Emailaddress) but it can be overwritten here

      fromName = 'Name Surname' - optional, can be set in module config (called Sender Name) but it can be overwritten here


      priority (3) - 1 = Highest | 2 = High | 3 = Normal | 4 = Low | 5 = Lowest

      dispositionNotification () or notification () - request a Disposition Notification


      subject ($subject) - subject of the message

      body ($textBody) - use this one alone to create and send plainText emailmessages

      bodyHTML ($htmlBody) - use this to create a Multipart Alternative Emailmessage (containing a HTML-Part and a Plaintext-Part as fallback)

      addSignature ( true | false ) - the default-behave is selectable in config screen, this can be overridden here
      (only available if a signature is defined in the config screen)

      attachment ($filename, $alternativeBasename = "") - add attachment file, optionally alternative basename


      send () - send the message(s) and return number of successful sent messages


      getResult () - returns a dump (array) with all recipients (to, cc, bcc) and settings you have selected with the message, the message subject and body, and lists of successfull addresses and failed addresses,


      logActivity ($logmessage) - you may log success if you want

      logError ($logmessage) - you may log warnings, too. - Errors are logged automaticaly
       
       
      useSentLog (true | false) - intended for usage with e.g. third party newsletter modules - tells the send() method to make usage of the sentLog-methods - the following three sentLog methods are hookable, e.g. if you don't want log into files you may provide your own storage, or add additional functionality here

      sentLogReset ()  - starts a new LogSession - Best usage would be interactively once when setting up a new Newsletter

      sentLogGet ()  - is called automaticly within the send() method - returns an array containing all previously used emailaddresses

      sentLogAdd ($emailaddress)  - is called automaticly within the send() method
       
      Changelog: https://github.com/horst-n/WireMailSmtp/blob/master/CHANGELOG.md
       
    • By ukyo
      Call ProcessWire API Functions Inside STRING
      Github Repo
      Current status : BETA
      Each called method must return string value !
      I added all functions, but not tested all. I focused page(), page()->render and field properties (label, description and notes). I also tested some basic pages() api calls.
      Your API calls must start with { and must end with }. For use multiple arguments inside functions, separate arguments with ~ char.
      NOTE If you pass directly arguments to api {page(title)}, this call will check for requestedApiCall()->get(arguments).
      USAGE
      processString(string, page, language); Get page title <?php $str = "You are here : {page:title}"; echo processString($str); ?> Get page children render result <?php $str = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.<hr>{page:render:children}"; echo processString($str); ?> Get homepage title <?php $str = "You can visit our <a hre='{pages(1):url}'>{pages:get(1):title}</a>"; echo processString($str); ?> Get title field label, description or notes <?php $str = "Our title field properties are : label: {label(title)} - description: {description(title)} - notes: {notes(title)}"; echo processString($str); ?> Multiple examples <?php $str = " <ul class='uk-list uk-list-striped'> <li><b>01: GET FIELD LABEL</b> <code>&#123;label(title)&#125;</code> <b>RESULT :</b> <code>{label(title)}</code></li> <li><b>02: GET FIELD LABEL WITH PREFIX</b> <code>&#123;label(title~=> )&#125;</code> <b>RESULT :</b> <code>{label(title~=> )}</code></li> <li><b>03: GET FIELD LABEL WITH SUFFIX</b> <code>&#123;label(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{label(title~~ <=)}</code></li> <li><b>04: GET FIELD DESCRIPTION</b> <code>&#123;description(title)&#125;</code> <b>RESULT :</b> <code>{description(title)}</code><br> <li><b>05: GET FIELD DESCRIPTION WITH PREFIX</b> <code>&#123;description(title~=> )&#125;</code> <b>RESULT :</b> <code>{description(title~=> )}</code></li> <li><b>06: GET FIELD DESCRIPTION WITH SUFFIX</b> <code>&#123;description(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{description(title~~ <=)}</code></li> <li><b>07: GET FIELD NOTES</b> <code>&#123;notes(title)&#125;</code> <b>RESULT :</b> <code>{notes(title)}</code><br> <li><b>08: GET FIELD NOTES WITH PREFIX</b> <code>&#123;notes(title~=> )&#125;</code> <b>RESULT :</b> <code>{notes(title~=> )}</code></li> <li><b>09: GET FIELD NOTES WITH SUFFIX</b> <code>&#123;notes(title~~ <=)&#125;</code> <b>RESULT :</b> <code>{notes(title~~ <=)}</code></li> <li><b>10: GET PAGE TITLE</b> <code>&#123;page(title)&#125;</code> <b>RESULT :</b> <code>{page(title)}</code></li> <li><b>11: GET PAGE TITLE</b> <code>&#123;page:title&#125;</code> <b>RESULT :</b> <code>{page:title}</code></li> <li><b>12: GET PAGE RENDER TITLE</b> <code>&#123;page:render:title&#125;</code> <b>RESULT :</b> <code>{page:render:title}</code></li> <li><b>12: GET HOMEPAGE TITLE</b> <code>&#123;pages:get(template=home):title&#125;</code> <b>RESULT :</b> <code>{pages:get(template=home):title}</code></li> <li><b>13: GET HOMEPAGE TEMPLATE ID</b> <code>&#123;pages:get(template=home):template:id&#125;</code> <b>RESULT :</b> <code>{pages:get(template=home):template:id}</code></li> </ul> "; echo processString($str); ?>
    • By Robin S
      This module corrects a few things that I find awkward about the "Add New Template" workflow in the PW admin. I opened a wishlist topic a while back because it would good to resolve some of these things in the core, but this module is a stopgap for now.
      Originally I was going to share these as a few standalone hooks, but decided to bundle them together in a configurable module instead. This module should be considered alpha until it has gone through some more testing.
      Add Template Enhancements
      Adds some efficiency enhancements when adding or cloning templates via admin.

      Features
      Derive template label from name: if you like to give each of your templates a label then this feature can save some time. When one or more new templates are added in admin a label is derived automatically from the name. There are options for underscore/hyphen replacement and capitalisation of the label. Edit template after add: when adding only a single template, the template is automatically opened for editing after it is added. Copy field contexts when cloning: this copies the field contexts (a.k.a. overrides such as column width, label and description) from the source template to the new template when using the "Duplicate/clone this template?" feature on the Advanced tab. Copy field contexts when duplicating fields: this copies the field contexts if you select the "Duplicate fields used by another template" option when adding a new template. Usage
      Install the Add Template Enhancements module.
      Configure the module settings according to what suits you.
       
      https://github.com/Toutouwai/AddTemplateEnhancements