Jump to content
Hardoman

Admin hook, image upload, watermark, PIM

Recommended Posts

Hello community,

we have a website running version 3.0.118. The owner would like to have a watermark merged to the images, that are being uploaded in the CKEditor as a requirement.
Image upload besides the CKEditor within galleries and single images works as a charm already. We also use croppable image 3 there. (PIM2)

To realize this requirement, I thought of using a hook in the admin area. So, I read a lot in our forums and tested this by adding a hook into the ready.php file.

$this->addHookAfter('InputfieldFile::fileAdded',function(HookEvent$event){
wire('log')->save('test','Image upload works');
...

The log entry is being created correctly. But when I try to use the pim/watermark-function like in a template, he cannot find the watermark-image anymore. Furthermore, when I try to get the page-id, it does not seem to be accessible, because the application does not seem to know how to reference it, or I dont know the right way to do so…

So my questions are:
 

  • Is this the right attempt at all or will there be another, better workaround?
  • It seems, I cannot access the page object (of the content page) within this scope or file but I would need it to save the processed image inside the right files/id folder
  • Would it be better to place the hook into the admin-template? (or admin.php)
     

Thanks for any hints in advance. 🙂

Share this post


Link to post
Share on other sites

You are on the right track. See also here:

Are you using tracy debugger? It can help a lot, eg using bd('hook fired'); will show you what's going on in the tracy bar (or using firelogger fl() can also be helpful.

  • Like 1

Share this post


Link to post
Share on other sites
15 minutes ago, Hardoman said:

But when I try to use the pim/watermark-function like in a template, he cannot find the watermark-image anymore.

How do you try to get this image?

15 minutes ago, Hardoman said:

Would it be better to place the hook into the admin-template? (or admin.php)

Doesn't really matter 🙂 

  • Like 1

Share this post


Link to post
Share on other sites
5 hours ago, Hardoman said:

So my questions are:
 

  • Is this the right attempt at all or will there be another, better workaround?
  • It seems, I cannot access the page object (of the content page) within this scope or file but I would need it to save the processed image inside the right files/id folder
  • Would it be better to place the hook into the admin-template? (or admin.php)

Hi @Hardoman

I post you a code example below that works for me since ages and also with recent PW versions. It includes watermarking too!

It is called in a custom module and the event is >before "InputfieldFile::fileAdded" <, but you can call it in ready.php too.

Hopefully it is of help for you. Otherwise please ask further. :)

    public function importImage($event) {

        $inputfield = $event->object;                      // handle to the image field
        if(!$inputfield instanceof InputfieldImage) {      // we need an images field, not a file field
            return;                                        // early return
        }

        if(version_compare(wire('config')->version, '2.8.0', '<')) {
            $p = $inputfield->value['page'];               // get the page, PW < 2.8
        } else {
            $p = $inputfield->attributes['value']->page;   // get the page, PW >= 2.8 | 3.0 (or only from 3.0.17+ ??)
        }

        if('images' != $inputfield->name) return;          // we assume a field with name: images
        if('album' != $p->template) return;                // don't do it on other pages than archive album

        $image = $event->argumentsByName('pagefile');      // get the image



        // prebuild variations
            // AdminThumb
            $image->height(260);

            // AlbumThumbnail
            $portrait = $image->height > $image->width;
            $w = 228;
            if($portrait) {
                $w1 = intval($w);
                $h1 = intval(($w1 / 3 * 4) + 38);
            } else {
                $w1 = intval($w);
                $h1 = intval(($w1 / 3 * 2));
            }
            $image->crop("width=$w1, height=$h1");

            // Slick-Slideshow
            $wmPng = $this->pages->get('id=13967')->getUnformatted('watermark')->first()->width(403);
            // sharpening added, quality from 80 to 90
                $master = $image->contain('width=1000, height=700, quality=100, sharpening=none');
                $master = $master->pim2Load('full', false)->watermarkLogo($wmPng)->setQuality(100)->setUpscaling(true)->setSharpening('none')->pimSave();
                $sizeArray = array(array(448, 336), array(678, 506), array(908, 676));
                foreach($sizeArray as $sizes) {
                    $master->size($sizes[0], $sizes[1], array('upscaling'=>false, 'cropping'=>false, 'quality'=>90, 'sharpening'=>'soft'));
                }
            // sharpening added, quality from 80 to 90
        // prebuild variations



        // check / import IPTC data
            $additionalInfo = array();
            $info = @getimagesize($image->filename, $additionalInfo);
            if($info !== false && is_array($additionalInfo) && isset($additionalInfo['APP13'])) {
                $iptc = iptcparse($additionalInfo["APP13"]);
                if(is_array($iptc) && isset($iptc["2#025"]) && is_array($iptc["2#025"]) && count($iptc["2#025"])>0) {
                    $tmp = $iptc["2#025"];
                    $tags = array();
                    foreach($tmp as $k=>$v) {
                        if(empty($v)) continue;
                        $tags[] = jhpTextConversion(trim(strtolower($v)));
                    }
                    $p->images->trackChange('tags');               // prepare page to keep track for changes
                    $image->tags = implode(', ', $tags);
                    $p->save('images');                            // save the page
                }
            }
        // check / import IPTC data

    }

 

  • Like 5

Share this post


Link to post
Share on other sites

Hello Bernhard,
hello Horst,

many thanks for your hints and the big code chunk sent by Horst. I'm still testing and will update this comment, when I am done or if there are more questions.

Thank you very much. 🙂

  • Like 1

Share this post


Link to post
Share on other sites

Hello Horst,

thanks again for your hints, the following solution works for me, replaces the original image and the merged image is usable in the editor afterwards:

(Code is embedded in ready.php)

$this->addHookBefore("InputfieldImage::fileAdded", function ($event) {

    // Get the image
    $image = $event->argumentsByName('pagefile');

    // Location of watermark image
    $pngAlphaImage = $config->paths->templates . 'watermark.png';

    //Save image with watermark
    $master = $image->pim2Load('full', false)->watermarkLogo($pngAlphaImage,'SE', 0)->pimSave();

    //Setting some variations
    $sizeArray = array(array(448, 336), array(678, 506), array(908, 676));

    foreach($sizeArray as $sizes) {
        $master->size($sizes[0], $sizes[1], array('upscaling'=>false, 'cropping'=>false, 'quality'=>90, 'sharpening'=>'soft'));
    }

    $image->setFilename($master);
    //Set generated image as main image
    $image->setOriginal($master);

});

 

  • Like 1

Share this post


Link to post
Share on other sites

Unfortunately, I have to re-open this topic once more. When we implement the function above, the pim-created image is saved as a variation along with the original image. If you now embed the watermark image and somebody removes the original image, all the variations are gone, so the pim-image will vanish as well and furthermore the user will get a warning.

I did not find out yet, where I can avoid the new image to be deleted when the original one is being deleted. 

 

So would there be a way to duplicate the watermark image that it would be treated like a separate orignal one? Probably by cloning the pagefile object or something like this?

Any help would be highly appreciated. Thank you.

Share this post


Link to post
Share on other sites

@Hardoman If I understand correct, you want to watermark the original image. Is this right?

If so, you may want to watermark the original image directly. This way you don't need to delete the original image and copy / move around the watermarked variation.

If you look into the PIM docs, you will find a description how to work on system files instead of Pageimage objects. This would be the way to go.

 

Quote

* (how) can I use the ImageManipulator with other imagefiles than PW-Pageimages?

You can load any imagefile from your servers filesystem into the ImageManipulator with:


$pim = wire('modules')->get('PageImageManipulator')->imLoad($imageFilename);
// or
$pim = $wire->modules->get('PageImageManipulator')->imLoad($imageFilename, $options);

You can directly with the imLoad-method pass specific $options or you can do a separate call to setOptions(). Then you do your desired actions and last but not least you call save()! Most time I think the original passed file gets overwritten with the manipulation result, but you are also able to save to a different name and  / or fileformat. If so, it is useful to get the final (sanitized) filename back after saveing.


$optionalNewFilename = $pim->setOptions($options)->height(360)->flip()->blur()->save();

Also you may call this in one line if you prefer:


if(false!==$wire->modules->get('PageImageManipulator')->imLoad($imageFilename,$options)->height(360)->flip()->blur()->save()) {
    // success !!
}

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

see this post, the 3 tip: https://processwire.com/talk/topic/4264-page-image-manipulator-1/?tab=comments#comment-41748

 

Share this post


Link to post
Share on other sites

@horst Thanks for your quick reply! 🙂

Quote

If I understand correct, you want to watermark the original image. Is this right?

We would like to offer both types original and watermarked image. So that the user would be able to choose between them and post them in the editor. This already works now but not after somebody deletes the original image from the array.

We already tried to clone the object but there still is some link the the variations and also in the cloned object, the variations disappear. Probably in this case its not good to put the hook into the ready.php file.

Share this post


Link to post
Share on other sites

@horst Little update, this might be helpful for explanation:

we quickly tested editing the PIM02.module file (around line 122) and that seems to work for our demand:

$suffix = str_replace('-', '', $prefix);
        $suffix = "{$suffix}";
//        $suffix = "pim2-{$suffix}";
        if (false === strpos($p['filename'], '.')) $suffix = '.' . $suffix;

After this modification the watermark image is still there and it would work, unless somebody would like to delete all the variations the common way.

🤔

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 gebeer
      I am happy to present my new fieldtype FieldtypeImageFromPage. It is made up of 2 modules:
      Fieldtype Image Reference From Another Page is a Fieldtype that stores a reference to a single image from another page. The image can be selected with the associated Inputfield.
      Inputfield Select Image From Page is an Inputfield to select a single image from images on a predefined page and it's children.
      And there also is a helper module that takes care of cleanup tasks.
      This module evolved out of a discussion about my other Module FieldtypeImagePicker.  It caters for use cases where a set of images is being reused multiple times across a site. With this fieldtype these images can be administered through a chosen page. All images uploaded to that page will be available in the inputfield.
      When to use ?
      Let editors choose an image from a set of images that is being used site-wide. Ideal for images that are being re-used across the site.
      Suited for images that are used on multiple pages throughout the site (e.g. icons).
      Other than the native ProcessWire images field, the images here are not stored per page. Only references to images on another page are stored. This has several advantages:
      one central place to organize images when images change, you only have to update them in one place. All references will be updated, too. (Provided the name of the image that has changed stays the same) Features
      Images can be manipulated like native ProcessWire images (resizing, cropping etc.) Image names are fully searchable through the API Accidental image deletion is prevented. When you want to delete an image from one of the pages that hold your site-wide images, the module searches all pages that use that image. If any page contains a reference to the image you are trying to delete, deletion will be prevented. You will get an error message to help you edit those pages and remove references there before you can finally delete the image. How to install and setup
      Download and install this module like any other modules in ProcessWire Create a page in the page tree that will hold your images. This page's template must have an images field Upload some images to the page you created in step 2 Create a new field. As type choose 'Image Reference From Another Page'. Save the field. In 'Details' Tab of the field choose the page you created in step 2 Click Save button Choose the images field name for the field that holds your images (on page template from step 2) Click Save button again Choose whether you want to include child pages of page from step 2 to supply images Add the field to any template You are now ready to use the field View of the inputfield on the page edit screen:

      View of the field settings

      The module can be installed from this github repo. Some more info in the README there, too.
      In my tests it was fairly stable. After receiving your valued feedback, I will eventually add it to the modules directory.
      My ideas for further improvement:
      - add ajax loading of thumbnails
      Happy to hear your feedback!
       
    • By aComAdi
      Hi,
      Have been working with ProcessWire for a few months now, successfully implementing several sites. I am compiling data management into modules for our clients. Several sites are using those modules now. The modules are using RockMigrations to install fileds, templates and pages.
      Today, I installed a new site. And now I am tripping over an issue that I cannot explain. Content on pages is organized in 'rows'. The users can add row by using RepeaterMatrix...then completing the fields to add data to the row. One particular content row has image fields. When I upload the images to the fields, all works as expected. The images appear in the RepeaterMatrix and I do find the images in assets/files/xxxx. But the images are not displayed in the front-end (see attachment). As you can see in the attachment, the various text and textarea fields in the RepeaterMatrix item are displayed correctly.
      I have done the following:
      Compare field settings to the existing implementations: they are identical Compare the RepeateMatrix settings and permissions to existing implementations: they are identical Change field name. No change. Delete field and created manually (including once with different name). No change. If I dump the element with Tracey, I get the following output:
      If Max Number = 1 null If Max Number = 0 count => 0
      page => "/processwire/repeaters/for-field-136/for-page-1/1574873590-62-1/" (60)
      field => "wk_inhalt_start_links_bild" (26)
      url => "/serverpath/site/assets/files/1046/" (30)
      path => "/serverpath/serverpath/serverpath/serverpath/site/assets/files/1046/" (56)
      items => array () I would venture that there is an issue regarding images on the shared server...but another content element on the site works just fine with images.
      Bit stumped right now. Especially considering that I made the same installation earlier today on a different server successfully. I would appreciate any ideas on where to investigate this issue.

    • By Martin Wuehr
      Hello everybody,
      I'm hosting a Processwire Installation for a client. It runs on Processwire 2.5.3. Over the years everything was fine but now there is an issue with one Image-Field in one Template. Trying to upload an Image the Error "Not enough Memory to load/resize" occure. Other Image-Fields in all other Templates working without any issue. The Images I Tried to upload are very small (600px * 420px). The Images blongs to a News feed, and worked before.
      I read about the problem in the forum but I can't get this solved. I have no access to the php.ini to modify the memory_limit.
      I tried to update the Processwire Verion but failed. (Tried 2.7 /2.8 / 3.2) Got Always Internal Server Error and in the error Log: 
      Compile Error:     Cannot redeclare PageEditFieldPermissionConfig()….
      Has anybody any idea how I can get this solved?
      Thank you so much
      Martin
       
    • By August
      Hi again, after trying pages2PDF, RockPDF and mpdf I'm not sure which of them I should use. Of course, there is also wirePDF.
      I merged mpdf with rockPDF, add a footer and a page in Landscape and that works, like in the code-snippet below but be am I on the right way?
      After that I tried a couple of times rendering an image. Nothing happend, the same with Pages2PDF too. I also copied an Image-URL within processwire and tried further getting an Image within the PDF-Document, but it still display only the red marked placeholder.
      I simply would like create an PDF on click from some Pages including the Images.
      Are there special requirements on Debian 10 with Apache and php 7.3 using Processwire 3.0.123.?
      Is there a guide that I didn't found?
      Is somebody out there who has a similar issue solved and would you be so kind to explain?
       
      $pdf = $modules->get('RockPdf'); $mpdf = $pdf->mpdf; # $mpdf->showImageErrors = true; $pdf->set('SetHeader', 'header text'); $mpdf->AddPage('L'); # $mpdf->Image(urlencode('site/assets/files/1845/image-2.275x200.jpg'), 0, 0, 210, 297, 'jpg', '', true, false); $pdf->set('SetFooter', ' <table width="100%"> <tr> <td width="33%">{DATE j.m.Y}</td>        <td width="33%" align="center">{PAGENO}/{nbpg}</td> <td width="33%" style="text-align: right;">whatever</td> </tr> </table>'); $pdf->show(); // generate pdf  
    • By martind
      hi,
      is it possible to change field parent_id from InputfieldPageListSelect to InputfieldPageAutocomplet by addHookAfter('ProcessPageEdit::buildFormContent')?
      thanks,
      martin
       
×
×
  • Create New...