Jump to content
teppo

Module: Version Control For Text Fields

Recommended Posts

This module provides simplified (no fancy diff etc. features available, at least yet) version control for text type fields. Originally introduced in another post as a proof of concept, I'm now considering it stable enough to deserve a thread of it's own here.

Just so that you know: I've tested this module in multiple ProcessWire installations, three or four different versions in total running on two different platforms, but it still hasn't seen too much real world use. Any information you folks can provide me about how well (or badly) it worked (or didn't work) for you would be considered extremely helpful! :)

So, what does it do?

When editing pages, fields with old revisions available show up with a new icon in their header bars. By hovering that icon you get a list of available revisions and by clicking any one of those the value of that particular field is reverted to that revision. No changes are made to page until you choose a revision and save the page, which means that you can keep switching between revisions to get an idea what's really changed without inadvertently causing any content to change.

How does it work?

Behind the scenes hooks provided by ProcessWire are utilized to catch page edits. If text fields (such as FieldtypeText, FieldtypeTextarea etc.) selected at module configuration to be tracked were changed, their values (along with some metadata) are saved to two custom database tables. See attached screenshots for better idea about how this thing works.

Please note that before you've selected at least one template + field combination to be tracked via module settings nothing will be saved to database!

Getting started

Module is available at GitHub: https://github.com/teppokoivula/VersionControlForTextFields. Here's a direct download link if that's what you prefer. Installation instructions etc. are available at README.md.

If you've got any questions, feel free to post them here or PM me!
 

post-175-0-28801100-1361741766_thumb.png

post-175-0-97751100-1361741767_thumb.png

  • Like 14

Share this post


Link to post
Share on other sites

Looks very useful, thanks teppo!

Will try out this soon. Does it also work for multi-language fields?

  • Like 1

Share this post


Link to post
Share on other sites

Just been playing around with this, and so far it's brilliant, and works great with frontend page editing as well.

Thanks so much for your hard work on it. I'll let you know if I come across any issues!

  • Like 1

Share this post


Link to post
Share on other sites

Really happy to see this out and in the modules directory! Thanks for your great work with this module! 

  • Like 1

Share this post


Link to post
Share on other sites

Nice work!

I was talking to ryan what seems like ages ago now about version control and I remember stumbling across this easy to use diff class that might help in a future version: https://github.com/chrisboulton/php-diff

EDIT: I just noticed that someone has built a useful jQuery merging tool that would also help of you follow the link above and read the readme :)

  • Like 2

Share this post


Link to post
Share on other sites

I'm happy to hear that you guys find this module useful. I haven't had too much (/any) time to work on this module yet (current status: spitting out essays for school at lightning speed..) but hopefully should get to use most of next weekend adding and fixing things here and there :)

Looks very useful, thanks teppo!
Will try out this soon. Does it also work for multi-language fields?

At the moment those arent supported, but that's going to be the very next thing I'll be adding (I hope.) Language-alternate fields are no problem since they're actually separate fields, but multi-language fields use slightly different schema and thus require some extra care here.

 
I actually tested what happens if you enable this module for multi-language field and the result was pretty much as expected: only version that gets saved is the original one (column "data" in field_fieldname table) and if you attempt to roll back an old revision all language versions are replaced with that one. Not exactly useful.. luckily I did kind of expect something like this to come up, so this shouldn't be a huge thing to implement :)

I was talking to ryan what seems like ages ago now about version control and I remember stumbling across this easy to use diff class that might help in a future version: https://github.com/c...oulton/php-diff

EDIT: I just noticed that someone has built a useful jQuery merging tool that would also help of you follow the link above and read the readme  :)

Thanks, Pete! I'll definitely take a look at these ASAP.

There were couple of PHP diff libraries I originally browsed through and this may have been one of those, can't really remember anymore. Originally I were a bit worried about including an external library like that with a module. Perhaps that's not such a bad thing after all -- and BSD license should definitely make it possible. Anyway, I'll check this library (and that jQuery merge tool you mentioned) properly as soon as I get some free time :)

Probably the most straightforward way to achieve diff-like capabilities would be building on current method (storing full data etc.) and then either running PHP diff at Process module and getting output via AJAX call or (what I originally planned to do, and still would kind of like to try out) use something like this JavaScript diff algorithm by John Resig.

  • Like 3

Share this post


Link to post
Share on other sites

Version 0.9.2 of this module (just pushed to GitHub) introduces support for multi-language fields. See commit details for more info.

I've also brought in some minor fixes etc. during this weekend, so if you've installed this module you should consider updating.

  • Like 5

Share this post


Link to post
Share on other sites

Finally tried it out and very cool module! Thanks a lot tepp for the work.

I had some time to get how to get it to work as I was looking for the configuration. I didn't realize there's two modules... only after reading the get started again slowly it clicked. I always looked in the process module.

Sometime those module that have more than one .module can get confusing, almost annoying. It would be cool in general to have modules grouped together. It's all there but sometimes when installing a new module hard to find if you don't know/remember what to look for.

I noticed when looking for help, that there's version 091 on modules.processwire.com but it downloaded the one from github anyway with modules manager, but wanted to let you know you'd have to update that version on modules.processwire.com to get recognized as new version in modules manager.

  • Like 1

Share this post


Link to post
Share on other sites

teppo - not sure if you want issues listed here or on github, but with the new version I am getting this error:

"Method VersionControlForTextFields::removeExcessRows does not exist or is not callable in this context"

Reverting to old version fixed it.

Share this post


Link to post
Share on other sites

@adrian: thanks for reporting this. That problem was introduced in a recent update, but I'm pretty sure I've fixed it already. Could you check that you're running latest version, 0.9.4?

Share this post


Link to post
Share on other sites

Sorry for the confusion teppo - I thought I was on the very latest version, but apparently I was one or so behind. All working again - thanks!

  • Like 1

Share this post


Link to post
Share on other sites

Finally tried it out and very cool module! Thanks a lot tepp for the work.

Thanks, really appreciate your feedback :)

I had some time to get how to get it to work as I was looking for the configuration. I didn't realize there's two modules... only after reading the get started again slowly it clicked. I always looked in the process module.

Sometime those module that have more than one .module can get confusing, almost annoying. It would be cool in general to have modules grouped together. It's all there but sometimes when installing a new module hard to find if you don't know/remember what to look for.

I know exactly what you're talking about, it's a bit frustrating.. especially since a lot of things I've worked on lately have been a combination of two or even three modules. Anyway, for now adding a notice to ProcessRevisionHistoryForTextFields.module about some settings being in VersionControlForTextFields.module (and vice versa) should help others avoid this problem.

I noticed when looking for help, that there's version 091 on modules.processwire.com but it downloaded the one from github anyway with modules manager, but wanted to let you know you'd have to update that version on modules.processwire.com to get recognized as new version in modules manager.

I haven't been keeping my modules 100% up to date in the modules directory, should probably start doing that right now. Thanks for pointing this out!

  • Like 1

Share this post


Link to post
Share on other sites

Just pushed version 1.0.0 (yay!) to GitHub. No huge improvements involved this time either, just some minor additions, comments, overall consistency checks etc.. and of course support for fantastic new CKEditor inputfield Ryan is working on  :)

One notable thing is that now tables created during install actually have proper (?) indexes included. If you've installed this module earlier and want to add these without uninstalling this module first, it's quite simple to do via MySQL client (I'm not familiar enough with PHPMyAdmin to say for sure, but this is probably easy to do there too):

CREATE INDEX fields_id ON version_control_for_text_fields (fields_id);
CREATE INDEX version_control_for_text_fields_id ON version_control_for_text_fields__data (version_control_for_text_fields_id);

Don't worry too much if this seems difficult; these won't make any difference before you've got at least ~50k rows of history data (and even then the difference is minimal.) They should make things a bit faster especially if your site is very large, constantly updated and/or you want to keep history data "forever."

  • Like 3

Share this post


Link to post
Share on other sites

Thanks teppo,

Just a note on that SQL command. The second one has:

ON version_control_for_text_fields_id__data
 

but it should just be:

ON version_control_for_text_fields__data
 
  • Like 1

Share this post


Link to post
Share on other sites

Thanks @adrian, fixed :)

Share this post


Link to post
Share on other sites

Thanks Teppo! Just installed it on a live site (after some testing) and it seems to work really sweet.

  • Like 1

Share this post


Link to post
Share on other sites

Hello, this module is a very good idea. I've installed the latest version (1.0.1) and configured following the instructions, but it doesn't work (no history options at body section - with tinyMCE). I'm using xampp 3.1.0 and latest ProcessWire 2.2.9. Please help.

Share this post


Link to post
Share on other sites

Hello, this module is a very good idea. I've installed the latest version (1.0.1) and configured following the instructions, but it doesn't work (no history options at body section - with tinyMCE). I'm using xampp 3.1.0 and latest ProcessWire 2.2.9. Please help.

Just tested this in 2.2.9 and everything seems to work here, so I'll have to ask couple of questions to find out what exactly could be wrong:

  • First of all, have you selected fields and templates from module settings? Both are required in order for any data to be gathered.
  • Are there rows in your version_control_for_text_fields database table? (It'd be helpful to know if any data is being stored at all..)
  • Is there anything strange in PW error log (/site/assets/logs/errors.txt) and are you getting any JavaScript errors?

It would also be helpful to know a bit more about your environment so that I can try to reproduce this problem myself -- things like what OS is your site running on, have you installed other 3rd party modules and are you using default admin template or something else. If you wish you could also PM me with any extra details.

Share this post


Link to post
Share on other sites

I experienced this too the first time. I uninstalled the module and set it up again. Don't really know what I did. Second and third site went smooth with the same setup.

Share this post


Link to post
Share on other sites

After install this module I changed something in my body field - and there was no history. But after second change the history appeared. So I think, that I didn't understand how it works and when it starts working - but it works fine :)

But I have another problem. History is viewable only by user with superuser permision. In my processwire I have also role with only view and edit pages permission. Is there any posibility to show history for this user?

Share this post


Link to post
Share on other sites

I've ran into it again. You have to save the page twice once you have installed the module. In retrospect this is quite obvious, but if you install the module and you look for the icon it's not there at first. There has to be history to show the history.

Teppo, is this module supposed to work with CKEditor? When I switch to another version it keeps loading. I'm getting a js error: Uncaught ReferenceError: tinyMCE is not defined. The field itself is configured as an CKeditor type. I'm running 2.3.0.

Share this post


Link to post
Share on other sites

@arjen: current behavior was supposed to be an improvement compared to how it used to work (show one version, which was always active, right after first save) but now I'm starting to think that perhaps it was a mistake. I'll have to think about this a bit more. There are quite a few possible solutions for improving this, I'm just not quite sure (yet) which one would work best here..  :)

About this error, are you already using latest version, 1.0.2? This issue was reported by @apeisa earlier (not in this thread though) and should be fixed now. If it still exists, I'll have to take another look at that one too.

  • Like 1

Share this post


Link to post
Share on other sites

An option would be to always show the icon. If a user clicks a field with no history a simple message like "There are no earlier versions of this field" would be sufficient.

I will look into the version tonight and I will report back.

  • Like 1

Share this post


Link to post
Share on other sites

I have to say when I first installed it also took a time to realize to change text and save before seeing an icon. But if I remember correctly I had to save and change 2 times to get it show up, is that intended? I think it would be better to show the icon from beginning to avoid confusion, and show a little text



edit: too slow...

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Soma and arjen for that suggestion, I'll implement something like that ASAP.. simplest solutions are often best ones too :)

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By MoritzLost
      Cacheable Placeholders
      This module allows you to have pieces of dynamic content inside cached output. This aims to solve the common problem of having a mostly cacheable site, but with pieces of dynamic output here and there.  Consider this simple example, where you want to output a custom greeting to the current user:
      <h1>Good morning, <?= ucfirst($user->name) ?></h1> This snippet means you can't use the template cache (at least for logged-in users), because each user has a different name. Even if 99% of your output is static, you can only cache the pieces that you know won't include this personal greeting. A more common example would be CSRF tokens for HTML forms - those need to be unique by definition, so you can't cache the form wholesale.
      This module solves this problem by introducing cacheable placeholders - small placeholder tokens that get replaced during every request. The replacement is done inside a Page::render hook so it runs during every request, even if the response is served from the template cache. So you can use something like this:
      <h1>Good morning, {{{greeting}}}</h1> Replacement tokens are defined with a callback function that produces the appropriate output and added to the module through a simple hook:
      // site/ready.php wire()->addHookAfter('CachePlaceholders::getTokens', function (HookEvent $e) { $tokens = $e->return; $tokens['greeting'] = [ 'callback' => function (array $tokenData) { return ucfirst(wire('user')->name); } ]; $e->return = $tokens; }); Tokens can also include parameters that are parsed and passed to the callback function. There are more fully annotated examples and step-by-step instructions in the README on Github!
      Features
      A simple and fast token parser that calls the appropriate callback and runs automatically. Tokens may include multiple named or positional parameters, as well as multi-value parameters. A manual mode that allows you to replace tokens in custom pieces of cached content (useful if you're using the $cache API). Some built-in tokens for common use-cases: CSRF-Tokens, replacing values from superglobals and producing random hexadecimal strings. The token format is completely customizable, all delimiters can be changed to avoid collisions with existing tag parsers or template languages. Links
      Github Repository & documentation Module directory If you are interested in learning more, the README is very extensive, with more usage examples, code samples and usage instructions!
    • By MoritzLost
      This module allows you to integrate hCaptcha bot / spam protection into ProcessWire forms. hCaptcha is a great alternative to Google ReCaptcha, especially if you are in the EU and need to comply with privacy regulations.

      The development of this module is sponsored by schwarzdesign.
      The module is built as an Inputfield, allowing you to integrate it into any ProcessWire form you want. It's primarily intended for frontend forms and can be added to Form Builder forms for automatic spam protection. There's a step-by-step guide for adding the hCaptcha widget to Form Builder forms in the README, as well as instructions for API usage.
      Features
      Inputfield that displays an hCaptcha widget in ProcessWire forms. The inputfield verifies the hCaptcha response upon submission, and adds a field error if it is invalid. All hCaptcha configuration options for the widget (theme, display size etc) can be changed through the inputfield configuration, as well as programmatically. hCaptcha script options can be changed through a hook. Error messages can be translated through ProcessWire's site translations. hCaptcha secret keys and site-keys can be set for each individual inputfield or globally in your config.php. Error codes and failures are logged to help you find configuration errors. Please check the README for setup instructions.
      Links
      Github Repository and documentation InputfieldHCaptcha in the module directory (pending approval) Screenshots (configuration)

      Screenshots (hCaptcha widget)

       
       

       
    • By joshua
      This module is (yet another) way for implementing a cookie management solution.
      Of course there are several other possibilities:
      - https://processwire.com/talk/topic/22920-klaro-cookie-consent-manager/
      - https://github.com/webmanufaktur/CookieManagementBanner
      - https://github.com/johannesdachsel/cookiemonster
      - https://www.oiljs.org/
      - ... and so on ...
      In this module you can configure which kind of cookie categories you want to manage:

      You can also enable the support for respecting the Do-Not-Track (DNT) header to don't annoy users, who already decided for all their browsing experience.
      Currently there are four possible cookie groups:
      - Necessary (always enabled)
      - Statistics
      - Marketing
      - External Media
      All groups can be renamed, so feel free to use other cookie group names. I just haven't found a way to implement a "repeater like" field as configurable module field ...
      When you want to load specific scripts ( like Google Analytics, Google Maps, ...) only after the user's content to this specific category of cookies, just use the following script syntax:
      <script type="text/plain" data-type="text/javascript" data-category="statistics" data-src="/path/to/your/statistic/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing" data-src="/path/to/your/mareketing/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="external_media" data-src="/path/to/your/external-media/script.js"></script> <script type="text/plain" data-type="text/javascript" data-category="marketing">console.log("Inline scripts are also working!");</script> The type has to be "optin" to get recognized by PrivacyWire, the data-attributes are giving hints, how the script shall be loaded, if the data-category is within the cookie consents of the user. These scripts are loaded asynchronously after the user made the decision.
      If you want to give the users the possibility to change their consent, you can use the following Textformatter:
      [[privacywire-choose-cookies]] It's planned to add also other Textformatters to opt-out of specific cookie groups or delete the whole consent cookie.
      You can also add a custom link to output the banner again with a link / button with following class:
      <a href="#" class="privacywire-show-options">Show Cookie Options</a> <button class="privacywire-show-options">Show Cookie Options</button> This module is still in development, but we already use it on several production websites.
      You find it here: PrivacyWire Git Repo
      Download as .zip
      I would love to hear your feedback 🙂
      CHANGELOG
      0.1.1 Debugging: fixed error during uninstall 0.1.0 Added new detection of async scripts for W3C Validation 0.0.6 CSS-Debugging for hiding unused buttons, added ProCache support for the JavaScript tag 0.0.5 Multi-language support included completely (also in TextFormatter). Added possibility to async load other assets (e.g. <img type="optin" data-category="marketing" data-src="https://via.placeholder.com/300x300">) 0.0.4 Added possibility to add an imprint link to the banner 0.0.3 Multi-language support for module config (still in development) 0.0.2 First release 0.0.1 Early development
    • By bernhard
      --- Please use RockFinder3 ---
    • By Craig
      I've been using Fathom Analytics for a while now and on a growing number of sites, so thought it was about time there was a PW module for it.
      WayFathomAnalytics
      WayFathomAnalytics is a group of modules which will allow you to view your Fathom Analytics dashboard in the PW admin panel and (optionally) automatically add and configure the tracking code on front-end pages.
      Links
      GitHub Readme & documentation Download Zip Modules directory Module settings screenshot What is Fathom Analytics?
      Fathom Analytics is a simple, privacy-focused website analytics tool for bloggers and businesses.

      Stop scrolling through pages of reports and collecting gobs of personal data about your visitors, both of which you probably don't need. Fathom is a simple and private website analytics platform that lets you focus on what's important: your business.
      Privacy focused Fast-loading dashboards, all data is on a single screen Easy to get what you need, no training required Unlimited email reports Private or public dashboard sharing Cookie notices not required (it doesn't use cookies or collect personal data) Displays: top content, top referrers, top goals and more
×
×
  • Create New...