Jump to content
jaro

AutoExportTemplatesAndFields enables continuous integration of template and field configuration changes

Recommended Posts

Hello,

in one of my current projects, we have a test and production stage with their own ProcessWire installations, and we regularly want to migrate template/field configuration to the next stage without migrating content as well. ProcessWire supports this via the import/export functionality in the admin GUI. However we (and some others) would like to do this as part of an automated process. There seem to have been some discussion on this topic and two existing modules that get pretty near our requirements:

However, they try to solve more then we need and for mindplay-dk's module, development seems to have discontinued. At that point I decided to build a more simple module with reduced scope that basically just makes ProcessWire's import/export automation-ready.

Thanks in advance for trying this out and any feedback!

About this Module

CAUTION: This module is incompatible with repeater fields and ProFields.

The module enables you to transfer template and field configuration from one processwire installation to another in an automated way.

  • Changes to templates or fields are exported to the file system immediately (so they can be added to source control together with changes in the template files)
  • The import script is designed to run from the command line (so it can be invoked from your build/deployment tool). On invocation in import mode,
    • a DB backup is created
    • template/field changes from the persist directory are imported into the DB
  • In restore mode, the import script can restore any of the DB backups previously saved

How to Use

  1. Make sure the module is installed in the source and destination ProcessWire environments.
  2. After installation of the module, you should check if the module's default persistDirectory configuration setting fits your requirements. The module will automatically export all fields, fieldgroups, and templates to JSON files in the directory specified by that setting. Note that the same setting is used by the import script as well, so if you change it, make sure you change it in all affected ProcessWire environments.
  3. The JSON files can be transferred to the destination ProcessWire environment.
  4. Running the import script from the command line will import template and field data in the destination ProcessWire environment.

Manual Installation

Caution: Beta software - do not use in a production environment without prior testing and regular back-ups.

Caution: This module is incompatible with repeater fields and ProFields.

In case automatic installation does not work, get the code at https://github.com/jaromic/pw-autoexport-tf/ and follow the instructions in README.md for manual installation.

Manual Uninstall

Delete the following files and directories from your module directory:

AutoExportTemplatesAndFields/
AutoExportTemplatesAndFields.module
 Download

Install from the module directory, clone the repository via GitHub, or download ZIP.

Edited by jaro
Statement about incompatibility added
  • Like 15

Share this post


Link to post
Share on other sites

Hi and welcome to the forums.

This sounds interesting. I definetly will try it out, but not soon. Maybe in a week or two.

The DB-backup integration looks good. :)

Do you have used it with namespaced PW version 3 too?

Share this post


Link to post
Share on other sites

Thanks, horst :)

Using that version in our project, I have developed and tested for 2.6 only so far. It does not use namespaces, so 3.x will probably not load the module. I will adapt and test with 2.7 and 3.x as soon as my time allows, hope to get to that within the next two weeks too.

  • Like 1

Share this post


Link to post
Share on other sites

Now, that's some nice first post to have in the forums, so first of all welcome here.

I just wanted to add a word of caution here. The export functionality should work well for core fieldtypes, but 3rd party fieldtypes might not export/import their settings correctly. Especially for more complex (db-wise) fieldtypes like Table or maybe Matrix it's often not so simple to export to a text format. E.g. FieldtypeOptions didn't export it's options for quite some time. 

Also I'd be cautious with calling modules discontinued, which is, at least for my module, not the truth. Not seeing a weekly changelog is not necessarily a bad thing. 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks, and sorry, I just corrected that statement about your module.

Even if it cannot handle all field types that some other modules contribute, I hope I'll be able to improve my module to the point where it reliably warns about field types causing problems.

Share this post


Link to post
Share on other sites

@jaro @LostKobrakai

<dream mode>

Not sure if this is a good idea or not, but could this module be made to automatically export migrations that are compatible with Benjamin's migrations module? This would allow his module's interface to be used on the importing side to select which migrations to import.

</dream mode>

Edited to add: Now I've actually tried this module, I think the dream outlined above is more of a delusion. As it stands, the module does seem like a very neat way to keep the state of the fields and templates under version control along with the template files; nice work, @jaro!

Share this post


Link to post
Share on other sites
On 3.9.2016 at 1:59 PM, netcarver said:

Not sure if this is a good idea or not, but could this module be made to automatically export migrations that are compatible with Benjamin's migrations module? This would allow his module's interface to be used on the importing side to select which migrations to import.

Sorry it took me a while to answer, and thanks for the input and for trying it out!

The module is all about ProcessWire's built-in import/export functionality, merely exposing and automating it. For the moment I'd rather have it become good and stable in this than doing both formats mediocrely. For example, there are still issues with some common field types, and I want to look into special cases during import that are handled specially by the GUI when doing it graphically.

On 12.7.2016 at 5:01 PM, horst said:

Do you have used it with namespaced PW version 3 too?

In the meantime I did some tests with ProcessWire versions 2 and 3. The module itself worked without any changes both in v2 and v3 installations (thanks to ProcessWire's namespace magic), but I had to do differentiate in the import script. v1.0.1 contains that and some small fixes.

  • Like 1

Share this post


Link to post
Share on other sites

Hi,

I Installed the "AutoExportTemplatesAndFields" and when creating repeater fields the module was affecting the fields editing.

I had two repeater fields: "repeater1" and "repeater2", the "repeater1" should repeat the "images1" field and the "repeater2" should repeat the "images2",

the problem was each time I edited one of them and change the repeated field the other assumed that modification. Example: editing the "repeater1" and change the field to "image3" the "repeater2" instead of having the "image2" has the field to be repeated assumed the field "image3".

After uninstall the "AutoExportTemplatesAndFields" module I could edit each repeater and assign different fields to them.

I hope you can find the issue it is a great module to use.

Thank you.

  • Like 3

Share this post


Link to post
Share on other sites
On 1.4.2017 at 5:31 PM, vmo said:

I had two repeater fields [...] the problem was each time I edited one of them and change the repeated field the other assumed that modification. [...] I hope you can find the issue it is a great module to use.

Hi, thanks for that bug report, and I'm glad you like that module! I hope I'll have some time to look into this soon. I have added it to the issues on github for now.

  • Like 1

Share this post


Link to post
Share on other sites
On 4/6/2017 at 2:25 AM, jaro said:

Hi, thanks for that bug report, and I'm glad you like that module! I hope I'll have some time to look into this soon. I have added it to the issues on github for now.

Hi i ran into the same issue und it cost me much time to find the culprit of it. Please at least post a big warning in the readme for users to be aware before installation since i suspect this can affect many users who have installed pro fields

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, ICF Church said:

Hi i ran into the same issue und it cost me much time to find the culprit of it. Please at least post a big warning in the readme for users to be aware before installation since i suspect this can affect many users who have installed pro fields

@ICF Church README has been updated. Thanks for your feedback.

  • Like 1

Share this post


Link to post
Share on other sites

This issue hit me a while back too with the RepeaterMatrix field. I ended up posting about it in the Profields support board but, embarrassingly, forgot to let you know about it at the time, jaro. My apologies to all for the oversight.

 

Share this post


Link to post
Share on other sites

The issue, which I'd like to call Agent Smith Bug, that caused a Repeater/RepeaterMatrix field copying itself onto other same type fields while erasing the contents of the fields happened to me inversely without warning. Fortunately, it happened on a site while it's in development. I installed the module way before while browsing for new modules in the directory, and I forgot it was ever installed. It was later I upgraded the core many times, and available modules with the ProcessWireUpgrade module and later I installed the ProFields.

I think we need a special cross-checking notification system, just like a product changes its price or availability in Amazon's shopping cart. One way it was achieved, while you're installing a module it shows a warning for the system version. Right there, a system should notify us with a critical warning that module x would possibly break the behavior of module y. In my case, it would be great if the ProFields installation notified me. But how can it know? (Reminds me the Project Insight scene of Winter Soldier) As humans, we can't check every issue, every board entry.  Hence we need a database, testers, modifiers, structural changes, etc. Too many resources, scratch this idea.

Share this post


Link to post
Share on other sites
On 1.4.2017 at 5:31 PM, vmo said:

I had two repeater fields: "repeater1" and "repeater2", the "repeater1" should repeat the "images1" field and the "repeater2" should repeat the "images2",

the problem was each time I edited one of them and change the repeated field the other assumed that modification. Example: editing the "repeater1" and change the field to "image3" the "repeater2" instead of having the "image2" has the field to be repeated assumed the field "image3".

 

On 2.11.2017 at 1:26 PM, adoxus said:

The issue, which I'd like to call Agent Smith Bug, that caused a Repeater/RepeaterMatrix field copying itself onto other same type fields while erasing the contents of the fields happened to me inversely without warning.

 

On 10.10.2017 at 1:34 PM, netcarver said:

This issue hit me a while back too with the RepeaterMatrix field.

 

On 9.10.2017 at 11:38 AM, ICF Church said:

Hi i ran into the same issue und it cost me much time to find the culprit of it.

 

Thanks guys for all the feedback.

I looked into this a little, and I was able to reproduce an instance of the problem using VMO's description with two repeater fields 'rep1' and 'rep2' and two text fields 'text1' and 'text2'. The assignment of text fields to repeater fields got mixed up if and only if the AutoExportTemplatesAndFieldsModule was installed.

I could narrow down the problem onto my use of ProcessWire's $field->getExportData() inside a hook 'after' ProcessPageView::finished. The problem is triggered when this function is called on the repeater fields in that hook, so the function seems to have side effects. I have added a minimal showcase for this called 'BreakRepeaterFields module' to the git repository, see module info summary for usage.

To sum this up: I am pretty confident there is no bug in my code directly causing the faulty behaviour. On the other hand one could not say that there is a bug in ProcessWire either, as my module is using an internal method which is not part of the documented API.

Best I can do for now is to declare this module incompatible with repeater fields and ProFields.

  • Thanks 1

Share this post


Link to post
Share on other sites

Thanks for looking into it @jaro!

Is there no possibility to check weather a field is / is used inside, a repeater and then treat it differently (or omitting it)? Since this solves a rather critical weakness of Processwire (imho), maybe @ryan can help out with this?

Share this post


Link to post
Share on other sites
7 minutes ago, noelboss said:

Thanks for looking into it @jaro!

Is there no possibility to check weather a field is / is used inside, a repeater and then treat it differently (or omitting it)? Since this solves a rather critical weakness of Processwire (imho), maybe @ryan can help out with this?

Fields could be omitted by type, but the output of this module would then not be a complete snapshot of templates and fields any more, which was its purpose in the first place. Do you think, such an incomplete snapshot (without repeater fields and similar) could still be useful for repeater field users?

Treating problematic fields differently could solve the problem, but the module would most probably have to be equipped with code for each problematic field type.

Yes of course, one or two hints from @ryan could be very helpful now :)

Share this post


Link to post
Share on other sites

I think a partial export is still better then breaking an entire system ;) So even if it does not do anything, it's still better to if-repeater-return than to do harm imho. You could still log a warning that there have been unsupported fields that need manual exporting so the user knows what fields need to be exported…

Now, as for me, i just had to manually copy a field (not repeater) that I otherwise could have just exported - imported… (which I now did via the db directly)…

Also, shouldn't it be possible to narrow down the problem even further now that we know what causes the problem? What happens if you use "getTableData()" directly?

 

  • Like 1

Share this post


Link to post
Share on other sites
50 minutes ago, noelboss said:

I think a partial export is still better then breaking an entire system ;) So even if it does not do anything, it's still better to if-repeater-return than to do harm imho. You could still log a warning that there have been unsupported fields that need manual exporting so the user knows what fields need to be exported…

So far, I haven't heard of any case where using this module "breaks an entire system". However, you are claiming that it "nuked [your] system" in your article as well (linking here). I must say I'm really surprised to read about what sounds far worse than the problems mentioned so far by you or anyone else in this thread. Can you please provide some details on what happened there? Thanks.

Share this post


Link to post
Share on other sites

Hi Jaro, sorry for the long delay.

Now, nuked is probably a strong word, sorry if that offended you, that was not my intention and I can change that.

Now to as what happened: I stored some Configuration (like meta-data, logo, global site info etc) of my site in a Repeater Matrix structure (would rather user functional fields but they don't support all kinds of fields like images etc.) – and I also used several other repeaters on my site. Now whenever I made changes to any of them, the other Repeaters where changed as well, deleting my work I put into creating them and also the data that each of the already existing repeaters held. Thus breaking my site in some cases (where it dependet on configurations beeing present) and losing work, data stored as well as work I put into structuring things.

For example: I created a repeater for Social Media Links and started filling these in. After that I would create another Repeater for Multiple Information Junks. – Now my Configuration Repeater would lose its data, its setup and the same happened with the Social Media Links repeater. I would lose its data plus its setup. I had to recreate the Configuration Repeater and the Social Media Repeater and input the data again.

Until i found the culprit, I lost quite some hours of development work. And it was not obvious from where the problem stemed. At first I thought Repeater was broken, or my setup was wrong (I'm fairly new to PW).

In my humble opinion, dataloss is probably the worst that could happen to a system. A PHP Error, no Problem, remove the module, fix the code. Loss of files – they are under GIT, some work might be lost but not much. But data loss, even more important if it's structural – thats really bad. Things get worse if it's not obvious what causes this data to disappear.

I think, all of this is the case here. Hope this explains it a bit better. If I can be of any help in solving this issue, let me know. BTW, you said

On 11/6/2017 at 10:10 AM, jaro said:

but the output of this module would then not be a complete snapshot of templates and fields any more

with this issue, this is not the case anyway because the module can not handle the repeaters correctly and thus also not export its config corretly, thus the output is not a complete snapshot in the first place ;)

 

Share this post


Link to post
Share on other sites

Sorry for the even longer delay – as always, the weeks before christmas are the busiest of the year.

On 9.11.2017 at 11:09 AM, noelboss said:

Now, nuked is probably a strong word, sorry if that offended you, that was not my intention and I can change that.

No worries, I don't feel offended personally, it's just bad PR and that it kind of looks like some careless coding of this module caused data loss. I'd appreciate if you could reword or just remove the link.

Thanks for the detailed explanation.

On 9.11.2017 at 11:09 AM, noelboss said:

with this issue, this is not the case anyway because the module can not handle the repeaters correctly and thus also not export its config corretly, thus the output is not a complete snapshot in the first place ;)

I agree, but that's not how I meant it anyway, I was referring to the partial export vs. clean fail design choice.

Sticking to the second, I have added a blacklist of known incompatible fieldtypes (containing only repeater so far) for now so the module will not only skip incompatible fields, but refuse to export all fields with a clear error message in that case.

  • Like 1

Share this post


Link to post
Share on other sites

Hi @jaro

Thanks for the update. Would it be possible to still have a partial export (after checking a confirmation or using module settings)?

I have removed the links :)

  • Like 1

Share this post


Link to post
Share on other sites

Hi @jaro,

I've been having a look at the Repeater issue and the BreakRepeaterFields demonstration.

Interestingly, the issue is not that fields are copied from one repeater to another. It is that the module interferes with the listing of fields when the repeater field settings are viewed in ProcessField, causing the fields of one repeater to appear in the AsmSelect of another repeater. So if you check the database the fields associated with each repeater is actually correct despite the incorrect listing shown in ProcessField. But if the user then saves the field in ProcessField it is at this point that the associated fields become incorrect.

Could you explain why the module needs to hook ProcessPageView::finished? This method fires on every page view, front-end and back-end. But most of these page views will have no connection to field settings or template settings changing. Instead of hooking this method, couldn't you hook only methods that are related to field and template settings? So some method in ProcessField and ProcessTemplate?

And also, the module is looping over all fields on every page view. Could you focus in on just the field that is being edited? So when field1 is edited in ProcessField, just export the data for field1 rather than looping over every field. This would avoid the situation where the data for repeater2 becomes involved when editing repeater1.

I should say that I've just had a brief look at the issue so far, so there might be good reasons why the module does what it does.

  • Like 4
  • Thanks 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 horst
      ---------------------------------------------------------------------------------------------------------------------------------
        when working with PW version 2.6+, please use Pim2, not Pim!
        read more here  on how to change from the older to the newer version in existing sites
      ---------------------------------------------------------------------------------------------------------------------------------
      PageImage Manipulator, API for version 1 & 2

      The Page Image Manipulator is a module that let you in a first place do ImageManipulations with your PageImages. - And in a second place there is the possibility to let it work on any imagefile that exists in your servers filesystem, regardless if it is a 'known PW-image'.

      The Page Image Manipulator is a Toolbox for Users and Moduledevelopers. It is written to be as close to the Core ImageSizer as possible. Besides the GD-filterfunctions it contains resize, crop, canvas, rotate, flip, sharpen, unsharpMask and 3 watermark methods.



      How does it work?

      You can enter the ImageManipulator by calling the method pim2Load(). After that you can chain together how many actions in what ever order you like. If your manipulation is finished, you call pimSave() to write the memory Image into a diskfile. pimSave() returns the PageImage-Object of the new written file so we are able to further use any known PW-image property or method. This way it integrates best into the ProcessWire flow.

      The three examples above put out the same visual result: a grayscale image with a width of 240px. Only the filenames will slightly differ.

      You have to define a name-prefix that you pass with the pimLoad() method. If the file with that prefix already exists, all operations are skipped and only the desired PageImage-Object gets returned by pimSave(). If you want to force recreation of the file, you can pass as second param a boolean true: pim2Load('myPrefix', true).

      You may also want to get rid of all variations at once? Than you can call $pageimage->pim2Load('myPrefix')->removePimVariations()!

      A complete list of all methods and actions are at the end of this post.
       
      You may also visit the post with tips & examples for users and module developers.


      How to Install
      Download the module Place the module files in /site/modules/PageImageManipulator/ In your admin, click Modules > Check for new modules Click "install" for PageImageManipulator Done! There are no configuration settings needed, just install and use it. Download    (version 0.2.0)
      get it from the Modules Directory History of origins

      http://processwire.com/talk/topic/3278-core-imagemanipulation/


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


      Page Image Manipulator - Methods

      * pimLoad  or  pim2Load, depends on the version you use!

      pimLoad($prefix, $param2=optional, $param3=optional)
      param 1: $prefix - (string) = mandatory! param 2: mixed, $forceRecreation or $options param 3: mixed, $forceRecreation or $options return: pim - (class handle) $options - (array) default is empty, see the next method for a list of valid options! $forceRecreation - (bool) default is false It check if the desired image variation exists, if not or if forceRecreation is set to true, it prepares all settings to get ready for image manipulation
      -------------------------------------------------------------------

      * setOptions

      setOptions(array $options)
      param: $options - (array) default is empty return: pim - (class handle) Takes an array with any number valid options / properties and set them by replacing the class-defaults and / or the global config defaults optionally set in the site/config.php under imageSizerOptions or imageManipulatorOptions.

      valid options are:
      quality = 1 - 100 (integer) upscaling = true | false (boolean) cropping = true | false (boolean) autoRotation =true | false (boolean) sharpening = 'none' | 'soft' | 'medium' | 'strong' (string) bgcolor = (array) css rgb or css rgba, first three values are integer 0-255 and optional 4 value is float 0-1, - default is array(255,255,255,0) thumbnailColorizeCustom = (array) rgb with values for colorize, integer -255 - 255 (this can be used to set a custom color when working together with Thumbnails-Module)
        outputFormat = 'gif' | 'jpg' | 'png' (Attention: outputFormat cannot be specified as global option in $config->imageManipulatorOptions!) set {singleOption} ($value)
      For every valid option there is also a single method that you can call, like setQuality(90), setUpscaling(false), etc.
      -------------------------------------------------------------------

      * pimSave

      pimSave()
      return: PageImage-Object If a new image is hold in memory, it saves the current content into a diskfile, according to the settings of filename, imagetype, targetFilename and outputFormat. Returns a PageImage-Object!
      -------------------------------------------------------------------

      * release

      release()
      return: void (nothing) if you, for what ever reason, first load image into memory but than do not save it, you should call release() to do the dishes! 😉 If you use pimSave() to leave the ImageManipulator, release() is called automatically.
      -------------------------------------------------------------------

      * getOptions

      getOptions()
      return: associative array with all final option values example:
      ["autoRotation"] bool(true) ["upscaling"] bool(false) ["cropping"] bool(true) ["quality"] int(90) ["sharpening"] string(6) "medium" ["targetFilename"] string(96) "/htdocs/site/assets/files/1124/pim_prefix_filename.jpg" ["outputFormat"] string(3) "jpg" get {singleOption} ()
      For every valid option there is also a single method that you can call, like getQuality(), getUpscaling(), etc. See method setOptions for a list of valid options!
      -------------------------------------------------------------------

      * getImageInfo

      getImageInfo()
      return: associative array with useful informations of source imagefile example:
      ["type"] string(3) "jpg" ["imageType"] int(2) ["mimetype"] string(10) "image/jpeg" ["width"] int(500) ["height"] int(331) ["landscape"] bool(true) ["ratio"] float(1.5105740181269) ["bits"] int(8) ["channels"] int(3) ["colspace"] string(9) "DeviceRGB" -------------------------------------------------------------------

      * getPimVariations

      getPimVariations()
      return: array of Pageimages Collect all pimVariations of this Pageimage as a Pageimages array of Pageimage objects. All variations created by the core ImageSizer are not included in the collection.
      -------------------------------------------------------------------

      * removePimVariations

      removePimVariations()
      return: pim - (class handle) Removes all image variations that was created using the PIM, all variations that are created by the core ImageSizer are left untouched!
      -------------------------------------------------------------------
      * width

      width($dst_width, $sharpen_mode=null)
      param: $dst_width - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the width, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes.
      -------------------------------------------------------------------

      * height

      height($dst_height, $sharpen_mode=null)
      param: $dst_height - (integer) param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you prioritize the height, like with pageimage. Additionally, after resizing, an automatic sharpening can be done with one of the three modes.
      -------------------------------------------------------------------

      * resize

      resize($dst_width=0, $dst_height=0, $sharpen_mode=null)
      param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 param: $auto_sharpen - (boolean) default is true was deleted with version 0.0.8, - sorry for breaking compatibility param: $sharpen_mode - (string) possible: 'none' | 'soft' | 'medium' | 'strong', default is 'soft' return: pim - (class handle) Is a call to resize where you have to set width and / or height, like with pageimage size(). Additionally, after resizing, an automatic sharpening can be done with one of the three modes.
      -------------------------------------------------------------------

      * stepResize

      stepResize($dst_width=0, $dst_height=0)
      param: $dst_width - (integer) default is 0 param: $dst_height - (integer) default is 0 return: pim - (class handle) this performs a resizing but with multiple little steps, each step followed by a soft sharpening. That way you can get better result of sharpened images.
      -------------------------------------------------------------------

      * sharpen

      sharpen($mode='soft')
      param: $mode - (string) possible values 'none' | 'soft'| 'medium'| 'strong' return: pim - (class handle) Applys sharpening to the current memory image. You can call it with one of the three predefined pattern, or you can pass an array with your own pattern.
      -------------------------------------------------------------------

      * unsharpMask

      unsharpMask($amount, $radius, $threshold)
      param: $amount - (integer) 0 - 500, default is 100 param: $radius - (float) 0.1 - 50, default is 0.5 param: $threshold - (integer) 0 - 255, default is 3 return: pim - (class handle) Applys sharpening to the current memory image like the equal named filter in photoshop.
      Credit for the used unsharp mask algorithm goes to Torstein Hønsi who has created the function back in 2003.
      -------------------------------------------------------------------

      * smooth

      smooth($level=127)
      param: $level - (integer) 1 - 255, default is 127 return: pim - (class handle) Smooth is the opposite of sharpen. You can define how strong it should be applied, 1 is low and 255 is strong.
      -------------------------------------------------------------------

      * blur

      blur()
      return: pim - (class handle) Blur is like smooth, but cannot called with a value. It seems to be similar like a result of smooth with a value greater than 200.
      -------------------------------------------------------------------

      * crop

      crop($pos_x, $pos_y, $width, $height)
      param: $pos_x - (integer) start position left param: $pos_y - (integer) start position top param: $width - (integer) horizontal length of desired image part param: $height - (integer) vertical length of desired image part return: pim - (class handle) This method cut out a part of the memory image.
      -------------------------------------------------------------------

      * canvas

      canvas($width, $height, $bgcolor, $position, $padding)
      param: $width = mixed, associative array with options or integer, - mandatory! param: $height = integer, - mandatory if $width is integer! param: $bgcolor = array with rgb or rgba, - default is array(255, 255, 255, 0) param: $position = one out of north, northwest, center, etc, - default is center param: $padding = integer as percent of canvas length, - default is 0 return: pim - (class handle) This method creates a canvas according to the given width and height and position the memory image onto it.
      You can pass an associative options array as the first and only param. With it you have to set width and height and optionally any other valid param. Or you have to set at least width and height as integers.
      Hint: If you want use transparency with rgba and your sourceImage isn't of type PNG, you have to define 'png' as outputFormat with your initially options array or, for example, like this: $image->pimLoad('prefix')->setOutputFormat('png')->canvas(300, 300, array(210,233,238,0.5), 'c', 5)->pimSave()
      -------------------------------------------------------------------

      * flip

      flip($vertical=false)
      param: $vertical - (boolean) default is false return: pim - (class handle) This flips the image horizontal by default. (mirroring)
      If the boolean param is set to true, it flips the image vertical instead.
      -------------------------------------------------------------------

      * rotate

      rotate($degree, $backgroundColor=127)
      param: $degree - (integer) valid is -360 0 360 param: $backgroundColor - (integer) valid is 0 - 255, default is 127 return: pim - (class handle) This rotates the image. Positive values for degree rotates clockwise, negative values counter clockwise. If you use other values than 90, 180, 270, the additional space gets filled with the defined background color.
      -------------------------------------------------------------------

      * brightness

      brightness($level)
      param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust brightness by defining a value between -255 and +255. Zero lets it unchanged, negative values results in darker images and positive values in lighter images.
      -------------------------------------------------------------------

      * contrast

      contrast($level)
      param: $level - (integer) -255 0 255 return: pim - (class handle) You can adjust contrast by defining a value between -255 and +255. Zero lets it unchanged, negative values results in lesser contrast and positive values in higher contrast.
      -------------------------------------------------------------------

      * grayscale

      grayscale()
      return: pim - (class handle) Turns an image into grayscale. Remove all colors.
      -------------------------------------------------------------------

      * sepia

      sepia()
      return: pim - (class handle) Turns the memory image into a colorized grayscale image with a predefined rgb-color that is known as "sepia".
      -------------------------------------------------------------------

      * colorize

      colorize($anyColor)
      param: $anyColor - (array) like css rgb or css rgba - but with values for rgb -255 - +255,  - value for alpha is float 0 - 1, 0 = transparent  1 = opaque return: pim - (class handle) Here you can adjust each of the RGB colors and optionally the alpha channel. Zero lets the channel unchanged whereas negative values results in lesser / darker parts of that channel and higher values in stronger saturisation of that channel.
      -------------------------------------------------------------------

      * negate

      negate()
      return: pim - (class handle) Turns an image into a "negative".
      -------------------------------------------------------------------

      * pixelate

      pixelate($blockSize=3)
      param: $blockSize - (integer) 1 - ??, default is 3 return: pim - (class handle) This apply the well known PixelLook to the memory image. It is stronger with higher values for blockSize.
      -------------------------------------------------------------------

      * emboss

      emboss()
      return: pim - (class handle) This apply the emboss effect to the memory image.
      -------------------------------------------------------------------

      * edgedetect

      edgedetect()
      return: pim - (class handle) This apply the edge-detect effect to the memory image.
      -------------------------------------------------------------------

      * getMemoryImage

      getMemoryImage()
      return: memoryimage - (GD-Resource) If you want apply something that isn't available with that class, you simply can check out the current memory image and apply your image - voodoo - stuff
      -------------------------------------------------------------------

      * setMemoryImage

      setMemoryImage($memoryImage)
      param: $memoryImage - (GD-Resource) return: pim - (class handle) If you are ready with your own image stuff, you can check in the memory image for further use with the class.
      -------------------------------------------------------------------

      * watermarkLogo

      watermarkLogo($pngAlphaImage, $position='center', $padding=2)
      param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW,
      - or: north, east, south, west, center, northeast, southeast, southwest, northwest
      default is 'center' param: $padding - (integer) 0 - 25, default is 5, padding to the borders in percent of the images length! return: pim - (class handle) You can pass a transparent image with its filename or as a PageImage to the method. If the watermark is bigger than the destination-image, it gets shrinked to fit into the targetimage. If it is a small watermark image you can define the position of it:
      NW - N - NE | | | W - C - E | | | SW - S - SE  
      The easiest and best way I have discovered to apply a big transparency watermark to an image is as follows:
      create a square transparent png image of e.g. 2000 x 2000 px, place your mark into the center with enough (percent) of space to the borders. You can see an example here! The $pngAlphaImage get centered and shrinked to fit into the memory image. No hassle with what width and / or height should I use?, how many space for the borders?, etc.
      -------------------------------------------------------------------

      * watermarkLogoTiled

      watermarkLogoTiled($pngAlphaImage)
      param: $pngAlphaImage - mixed [systemfilepath or PageImageObject] to/from a PNG with transparency return: pim - (class handle) Here you have to pass a tile png with transparency (e.g. something between 150-300 px?) to your bigger images. It got repeated all over the memory image starting at the top left corner.
      -------------------------------------------------------------------

      * watermarkText

      watermarkText($text, $size=10, $position='center', $padding=2, $opacity=50, $trueTypeFont=null)
      param: $text - (string) the text that you want to display on the image param: $size - (integer) 1 - 100, unit = points, good value seems to be around 10 to 15 param: $position - (string) is one out of: N, E, S, W, C, NE, SE, SW, NW,
      - or: north, east, south, west, center, northeast, southeast, southwest, northwest
      default is 'center' param: $padding - (integer) 0 - 25, default is 2, padding to the borders in percent of the images length! param: $opacity- (integer) 1 - 100, default is 50 param: $trueTypeFont - (string) systemfilepath to a TrueTypeFont, default is freesansbold.ttf (is GPL & comes with the module) return: pim - (class handle) Here you can display (dynamic) text with transparency over the memory image. You have to define your text, and optionally size, position, padding, opacity for it. And if you don't like the default font, freesansbold, you have to point to a TrueTypeFont-File of your choice.
      Please have a look to example output: http://processwire.com/talk/topic/4264-release-page-image-manipulator/page-2#entry41989
      -------------------------------------------------------------------





      PageImage Manipulator - Example Output


    • By d'Hinnisdaël
      Format Datetime fields as Carbon instances.
      You can find the latest release and the complete readme on Github.
      Installation
      composer require daun/datetime-carbon-format Usage
      All Datetime fields will now be formatted as Carbon instances instead of strings. Some examples:
      // $page->date is a Datetime field // Output format: j/n/Y echo $page->date; // 20/10/2020 echo $page->date->add('7 days'); // 27/10/2020 echo $page->date->format('l, F j'); // Monday, October 20 echo $page->date->year; // 2020 echo $page->date->diffForHumans(); // 28 minutes ago Frontend only
      The ProcessWire admin seems to expect datetime fields to be strings. This module will only return Carbon instances on frontend page views.
      Date output format
      When casting a Carbon instance to a string (usually when outputting the field in a template), the field's date output format will be respected.
      Links
      GitHub • Readme • Carbon docs
       
       
      PS. I remember reading about a Carbon module in a recent newsletter, but couldn't find it anywhere. Was that you, @bernhard?
    • By MoritzLost
      TrelloWire
      This is a module that allows you to automatically create Trello cards for ProcessWire pages and update them when the pages are updated. This allows you to setup connected workflows. Card properties and change handling behaviour can be customized through the extensive module configuration. Every action the module performs is hookable, so you can modify when and how cards are created as much as you need to. The module also contains an API-component that makes it easy to make requests to the Trello API and build your own connected ProcessWire-Trello workflows.
      Warning: This module requires ProcessWire 3.0.167 which is above the current stable master release at the moment.
      Features
      All the things the module can do for you without any custom code: Create a new card on Trello whenever a page is added or published (you can select applicable templates). Configure the target board, target list, name and description for new cards. Add default labels and checklists to the card. Update the card whenever the page is updated (optional). When the status of the card changes (published / unpublished, hidden / unhidden, trashed / restored or deleted), move the card to a different list or archive or delete it (configurable). You can extend this through hooks in many ways: Modifiy when and how cards are created. Modify the card properties (Target board & list, title, description, et c.) before they are sent to Trello. Create your own workflows by utilizing an API helper class with many convenient utility methods to access the Trello API directly. Feedback & Future Plans
      Let me know what you think! In particular:
      If you find any bugs report them here or on Github, I'll try to fix them. This module was born out of a use-case for a client project where we manage new form submissions through Trello. I'm not sure how many use-cases there are for this module. If you do use it, tell me about it! The Trello API is pretty extensive, I'll try to add some more helper methods to the TrelloWireApi class (let me know if you need anything in particular). I'll think about how the module can support different workflows that include Twig – talk to me if you have a use-case! Next steps could be a dashboard to manage pages that are connected to a Trello card, or a new section in the settings tab to manage the Trello connection. But it depends on whether there is any interest in this 🙂 Links
      Repository on Github Complete module documentation (getting started, configuration & API documentation) TrelloWire in the modules directory Module configuration

    • By David Karich
      ProcessWire InputfieldRepeaterMatrixDuplicate
      Thanks to the great ProModule "RepeaterMatrix" I have the possibility to create complex repeater items. With it I have created a quite powerful page builder. Many different content modules, with many more possible design options. The RepeaterMatrix module supports the cloning of items, but only within the same page. Now I often have the case that very design-intensive pages and items are created. If you want to use a content module on a different page (e.g. in the same design), you have to rebuild each item manually every time.
      This module extends the commercial ProModule "RepeaterMatrix" by the function to duplicate repeater items from one page to another page. The condition is that the target field is the same matrix field from which the item is duplicated. This module is currently understood as proof of concept. There are a few limitations that need to be considered. The intention of the module is that this functionality is integrated into the core of RepeaterMatrix and does not require an extra module.
      Check out the screencast
      What the module can do
      Duplicate multible repeater items from one page to another No matter how complex the item is Full support for file and image fields Multilingual support Support of Min and Max settings Live synchronization of clipboard between multiple browser tabs. Copy an item and simply switch the browser tab to the target page and you will immediately see the past button Support of multiple RepeaterMatrix fields on one page Configurable which roles and fields are excluded Configurable dialogs for copy and paste Duplicated items are automatically pasted to the end of the target field and set to hidden status so that changes are not directly published Automatic clipboard update when other items are picked Automatically removes old clipboard data if it is not pasted within 6 hours Delete clipboard itself by clicking the selected item again Benefit: unbelievably fast workflow and content replication What the module can't do
      Before an item can be duplicated in its current version, the source page must be saved. This means that if you make changes to an item and copy this, the old saved state will be duplicated Dynamic loading is currently not possible. Means no AJAX. When pasting, the target page is saved completely No support for nested repeater items. Currently only first level items can be duplicated. Means a repeater field in a repeater field cannot be duplicated. Workaround: simply duplicate the parent item Dynamic reloading and adding of repeater items cannot be registered. Several interfaces and events from the core are missing. The initialization occurs only once after the page load event Attention, please note!
      Nested repeaters cannot be supported technically. Therefore a check is made to prevent this. However, a nested repeater can only be detected if the field name ends for example with "_repeater1234". For example, if your MatrixRepeater field is named like this: "content_repeater" or "content_repeater123", this field is identified as nested and the module does not load. In version 2.0.1 the identification has been changed so that a field ending with the name repeater is only detected as nested if at least a two-digit number sequence follows. But to avoid this problem completely, make sure that your repeater matrix field does NOT end with the name "repeater".
      Changelog
       
      2.0.1
      Bug fix: Thanks to @ngrmm I could discover a bug which causes that the module cannot be loaded if the MatrixRepeater field ends with the name "repeater". The code was adjusted and information about the problem was provided 2.0.0
      Feature: Copy multiple items at once! The fundament for copying multiple items was created by @Autofahrn - THX! Feature: Optionally you can disable the copy and/or paste dialog Bug fix: A fix suggestion when additional and normal repeater fields are present was contributed by @joshua - THX! 1.0.4
      Bug fix: Various bug fixes and improvements in live synchronization Bug fix: Items are no longer inserted when the normal save button is clicked. Only when the past button is explicitly clicked Feature: Support of multiple repeater fields in one page Feature: Support of repeater Min/Max settings Feature: Configurable roles and fields Enhancement: Improved clipboard management Enhancement: Documentation improvement Enhancement: Corrected few typos #1 1.0.3
      Feature: Live synchronization Enhancement: Load the module only in the backend Enhancement: Documentation improvement 1.0.2
      Bug fix: Various bug fixes and improvements in JS functions Enhancement: Documentation improvement Enhancement: Corrected few typos 1.0.1
      Bug fix: Various bug fixes and improvements in the duplication process 1.0.0
      Initial release Support this module
      If this module is useful for you, I am very thankful for your small donation: Donate 5,- Euro (via PayPal – or an amount of your choice. Thank you!)
      Download this module (Version 2.0.1)
      > Github: https://github.com/FlipZoomMedia/InputfieldRepeaterMatrixDuplicate
      > PW module directory: https://modules.processwire.com/modules/inputfield-repeater-matrix-duplicate/
      > Old stable version (1.0.4): https://github.com/FlipZoomMedia/InputfieldRepeaterMatrixDuplicate/releases/tag/1.0.4
×
×
  • Create New...