Jump to content
David Karich

Module: AIOM+ (All In One Minify) for CSS, LESS, JS and HTML

Recommended Posts

                   I have used AIOM on all website which have been developed by us on processwire. Recently one of our site started to throw error and it was working fine tilll few days ago.Error is

                  " Error:     Exception: The combined js file can not be written. Check if the script has sufficient permissions ".

                   We tried allowing the module  permission with 777 and also changed the permission in the config file and have failed.AIOM is able to create file but is not able to write anything in that file.

                   We are using AIOM version 3.2.1 on Processwire 2.5.3.

                  

Thanks

Had a strange and horrific experience on Thursday when a site i was working on suddenly could no longer create the new cache files...;

i made a change to 1 line of a CSS file on the live site, and then that's when things went sideways.

The CSS minify script started to fail and causing PHP timeouts, and then this took the whole site down, every page, and the admin. 

this is the error:

2015-05-09 18:49:28    guest    **site-name**    Error:     Maximum execution time of 60 seconds exceeded (line 87 of /home/public_html/site/modules/AllInOneMinify/lib/cssmin.php)

How I fixed it (for the moment):

1.) uninstall AIOM+

2.) Replace with new copy

3.) Re-install it, and set on dev mode, no HTML minify.

this thankfully fixed the issue, but all in all the site was down for quite a while during this, and it made me realize that this part of the chain in my websites is a weak link, especially if it can fail, in that the site cannot run without the css and js files.

Typically I would always have $minifyCSS and $minifyJS vars in my _init.php which in this case i could have simply set to false and then no problem, i could have gone and fixed the AIOM+ issue while the site ran.

But for this site I hadn't set that up yet and also I am using conditional loading and hadn't worked out the script to load the individual assets if one of those vars is false.

After looking a bit at the module, i came up with this solution for disabling AIOM+ based on a boolean var in your init:

if($minifyJS == true) {
	echo '<script type="text/javascript" src="' . AIOM::JS($jsfiles) . '"></script>';
} else { 	
	listAssets($jsfiles);
} // END IF

this is the function (may not be 100% perfect, still testing, but works ok so far):

// use this to echo the assets in the AOIM+ array
function listAssets($asset_files) {

	$templates		= wire('config')->urls->templates;
        $current_page   = wire('page');
	// testing
	//$current_page	= wire('pages')->get(1023);
	
        foreach ($asset_files as $asset_file) {

            if ( is_array($asset_file) AND isset($asset_file['loadOn']) AND isset($asset_file['files']) ) {

				$selector = $asset_file['loadOn'];
				if(!$current_page->is($selector)) continue;

                if(is_array($asset_file['files'])) {
                    
                    foreach ($asset_file['files'] as $_asset_file) {
                            echo "<script src='{$templates}{$_asset_file}'></script>\n";
                        }

                    } else {
                        echo "<script src='{$templates}{$asset_file}'></script>\n";
                    }

            } else {
                echo "<script src='{$templates}{$asset_file}'></script>\n";
            }
        }

}

In summary, i think that maybe there should be an emergency shut off in AIOM+, because without the method described above, how would you keep a site online say if AIOM+ was just totally failing?

  • Like 2

Share this post


Link to post
Share on other sites
In summary, i think that maybe there should be an emergency shut off in AIOM+, because without the method described above, how would you keep a site online say if AIOM+ was just totally failing?

Yes, I have also experienced a few weeks back exactly the same as you describe here, and resolved it essentially the same way. As with you I had unwanted downtime while I sorted the issue. As a result I've also implemented a system similar to yours, which makes me think others are probably doing the same also. If this is something that is being repeated on multiple sites then ideally it should become part of the AIOM module.

Share this post


Link to post
Share on other sites

yes, it seems undeniable that AIOM+, which is otherwise a godsend plugin, has the possible side effect of tanking an entire website, front and backend, without warning. The cause is probably some change in the permissions, or who knows what; in my case the css minify was timing out in php, but had worked fine for a year before that.

The module would seem to leave no recourse in the event that it fails and the developer has not taken steps as described above and in use by @muzzer and myself to provide an alternate way of outputting the assets.

I think the module should come with instructions and warnings about these possible consequences, and that function i posted or one that does the same thing, should be part of the module so that if the user sets emergency shut off, it just lists the files in the arrays that have been passed into the class as single assets...

it would also make sense for there to be a simple api for the module in the event that a site has tanked, to enable emergency shutoff; the api could also possibly allow for cache clearing, enable/disable dev mode and enable/disable html minify (this could also allow one to minify html or not on a per template basis, per horst's request..)

  • Like 3

Share this post


Link to post
Share on other sites

I think I fixed the Maximum Execution Time Error by fixing an unclosed comment tag within a CSS file.

At least on my local machine it's working, should work live, too but haven't tested it yet..

And I ran into an issue with JS minification "Error JSMin: unterminated byte.."

Fixed it by renaming already minified files to NAME.min.js, seems to work for now :)

Why isn't AIOM clearing cached files when creating new once, like replacing them. I had quite a long expiration time and had sometimes over 80 cached files in cache..?

Maybe my fault^^

  • Like 1

Share this post


Link to post
Share on other sites

I really like the domain sharding option of AIOM. I even grab this setting in my templates to deliver all images from a cookiless domain (usually in combination with minimize.pw). It looks something like this:

// cache cookieless domain for static content as set in AllInOneMinify configuration
$my_static_domain_setting_source = wire('modules')->getModuleConfigData('AllInOneMinify');
$my_static_domain = $my_static_domain_setting_source['domain_sharding'];

// use static domain in the template like this
echo '<img src="' . $my_static_domain . $page->image->minimize()->url . '" />';

While this works, it’s a bit laborious.

Wouldn’t it be a good idea to add an additional checkbox in the module’s settings to set an option “deliver all images from cookiless domain”?

Hooking into the page rendering process and replacing every relative image source (= not starting with "http") or image source starting with “http://” and the site’s default domain as set in config.php should do the trick – if I’m not too naive.

  • Like 1

Share this post


Link to post
Share on other sites

Hi there,

I've just copied a new site from development to a server and when I tried to run from the server, there was no styling or javascript. After doing some digging about, I noticed that the AllInOneMinify .css and .js files were both empty (zero file length).

All is fine on the local machine. Any idea what might be causing this?

The module seems to be running OK because if you delete the files, it recreates them when you try and load the site. It's just that they are empty?

Any suggestions much appreciated! :)

Many thanks.

Edited by LostKobrakai
Moved to AIOM support topic

Share this post


Link to post
Share on other sites

Hy there,

Great Module! I use "AIOM" in conjunction with "Template Engine Factory". The HTML minify function ist not working, if i have both modules installed. Maybe it it because the minify process is hooked to Page::render and not to Templatefile::render?

Share this post


Link to post
Share on other sites

Fantastic module. Huge shame that it removes the space between tags at the moment.

<p><strong>Text</strong> <em>(text)</em></p>

The above would then be right next to each other. Will check out the parser code when I get a mo.

Share this post


Link to post
Share on other sites

Thank you for this module!

I have a string "../modules/FieldtypeLeafletMapMarker/assets/leaflet/leaflet.css" in my styles array.

But AIOM cannot read it. I get

Warning: file_get_contents(): Filename cannot be empty

But it should be the correct relative path to leaflet.css seen from site/templates/_main.php.

I don't understand why it is not working. Passing in "css/styles.css" is working fine.

I read Soma's post and agree that it should be possible to pass in files from outside /templates. I already tried his proposed fix in conjunction with passing in "/site/modules/FieldtypeLeafletMapMarker/assets/leaflet/leaflet.css" but that didn't work either for me.

Share this post


Link to post
Share on other sites

I guess you enabled "directory traversal" in AIOMs module settings?

  • Like 1

Share this post


Link to post
Share on other sites

I guess you enabled "directory traversal" in AIOMs module settings?

Thank you for the hint. I had not enabled that option. After enabling it, all is fine now. Should have looked at the module settings more carefully  :blush:

  • Like 1

Share this post


Link to post
Share on other sites

Your link points to a 404 for me

Share this post


Link to post
Share on other sites

Hi Tom.,

Could you specify what kind of security issue there is?

Share this post


Link to post
Share on other sites

Hi Tom.,

Could you specify what kind of security issue there is?

Here is the security issue - https://github.com/conclurer/ProcessWire-AIOM-All-In-One-Minify/issues/44

@Tom...404 returned at the link you've provided

How strange, I get a 404 when clicking the link, however if I focus the URL bar and press enter it works. Here is a link to the pull request - https://github.com/conclurer/ProcessWire-AIOM-All-In-One-Minify/pull/53

  • Like 1

Share this post


Link to post
Share on other sites

I couldn't get the AIOM Module running and received error warnings. Now I came across the warning on the Modules page about not using it until the problems are solved.

So I tried to uninstall the module, but with no success. I got this error:

The cache folder (/home/httpd/vhosts/…/dev/site/assets/aiom/) and files could not be removed.

So I cannot uninstall the module.

Is there a way to uninstall it manually?

Share this post


Link to post
Share on other sites

File could not be removed or module could not be removed? If file, then just delete it manually. If module, then you can remove it via phpMyAdmin or similar. Find the table called 'modules' in your ProcessWire database, then find the row with this module's class name, i.e .AllInOneMinify  (check in the column class) and delete that row. You might want to first backup your db just in case :-)

Edited by kongondo
  • Like 2

Share this post


Link to post
Share on other sites

The module could not be removed.

So I deleted the row in the "modules" table, and also the files from the "site->modules" folder and the "aiom" folder from "site->assets".

No I get this error, when I call the frontend:

The server encountered an internal error or misconfiguration and was unable to complete your request.

Error has been logged.

But there is nothing in the pw log, nor in the servers log.

I can login in the backend. When logged in, I can view the site.

Edit:

I just became aware that it could have been because of the site cache. I now safed the home page again and now the frontend works again.

  • Like 2

Share this post


Link to post
Share on other sites
Hi guys,

I have just released an update to version 3.2.2 on Github. It fixes the security issue with the CHMOD, the problem with many files and has a better detection of changes to files.

Sorry that it took so long. But we currently have a lot to do. The module will continue maintained. AIOM4 is on the to-do list.

Best regards,

David

  • Like 5

Share this post


Link to post
Share on other sites

Line 713 typo: $_timespamp

    private static function _getCacheName($files, $prefix = 'css_', $ext = '.css') {
        
        // ------------------------------------------------------------------------
        // Initialize timestamp variable.
        // ------------------------------------------------------------------------
        $_timestamp = '';

        // ------------------------------------------------------------------------
        // Calculate timestamp of all files
        // ------------------------------------------------------------------------
        foreach ($files as $file) {
            $_timestamp = ($_timespamp + $file['last_modified']);
        }

        // ------------------------------------------------------------------------
        // Create a unique MD5 file name with the specified prefix.
        // ------------------------------------------------------------------------
        return (self::$developmentMode !== true) ? $prefix.md5($_timestamp).$ext : $prefix.md5($_timestamp).'_dev'.$ext;
    }

  • Like 4

Share this post


Link to post
Share on other sites

Line 713 typo: $_timespamp

    private static function _getCacheName($files, $prefix = 'css_', $ext = '.css') {
        
        // ------------------------------------------------------------------------
        // Initialize timestamp variable.
        // ------------------------------------------------------------------------
        $_timestamp = '';

        // ------------------------------------------------------------------------
        // Calculate timestamp of all files
        // ------------------------------------------------------------------------
        foreach ($files as $file) {
            $_timestamp = ($_timespamp + $file['last_modified']);
        }

        // ------------------------------------------------------------------------
        // Create a unique MD5 file name with the specified prefix.
        // ------------------------------------------------------------------------
        return (self::$developmentMode !== true) ? $prefix.md5($_timestamp).$ext : $prefix.md5($_timestamp).'_dev'.$ext;
    }

Thanks Steve, I've fixed the problem in version 3.2.3. It was late at night. :-[ The update is available on Github.

  • Like 1

Share this post


Link to post
Share on other sites

After updating to 3.2.3 I get the an error 500 and cannot login to backend. Debugging shows the following error message:

Cannot redeclare class AIOM (line 1021 of /home/.sites/......../web/site/modules/AllInOneMinify/AllInOneMinify.module)

This is the code on line 1021:

class AIOM extends AllInOneMinify {}

???

Edit: Solved! I had 2 instances of AIOM with different file names so the class was 2 times declared. Now it works!!

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 teppo
      Needed a really simple solution to embed audio files within page content and couldn't find a module for that, so here we go. Textformatter Audio Embed works a bit like Textformatter Video Embed, converting this:
      <p>https://www.domain.tld/path/to/file.mp3</p> Into this:
      <audio controls class="TextformatterAudioEmbed"> <source src="https://www.domain.tld/path/to/file.mp3" type="audio/mpeg"> </audio> The audio element has pretty good browser support, so quite often this should be enough to get things rolling 🙂
      GitHub repository: https://github.com/teppokoivula/TextformatterAudioEmbed Modules directory: https://modules.processwire.com/modules/textformatter-audio-embed/
    • By Richard Jedlička
      Tense    
      Tense (Test ENvironment Setup & Execution) is a command-line tool to easily run tests agains multiple versions of ProcessWire CMF.
      Are you building a module, or a template and you need to make sure it works in all supported ProcessWire versions? Then Tense is exactly what you need. Write the tests in any testing framework, tell Tense which ProcessWire versions you are interested in and it will do the rest for you.

      See example or see usage in a real project.
      How to use?
      1. Install it: 
      composer global require uiii/tense 2. Create tense.yml config:
      tense init 3. Run it:
      tense run  
      For detailed instructions see Github page: https://github.com/uiii/tense
       
      This is made possible thanks to the great wireshell tool by @justb3a, @marcus and others.
       
      What do you think about it? Do you find it useful? Do you have some idea? Did you find some bug? Tell me you opinion. Write it here or in the issue tracker.
    • By Chris Bennett
      Hi all, I am going round and round in circles and would greatly appreciate if anyone can point me in the right direction.
      I am sure I am doing something dumb, or missing something I should know, but don't. Story of my life 😉

      Playing round with a module and my basic problem is I want to upload an image and also use InputfieldMarkup and other Inputfields.
      Going back and forth between trying an api generated page defining Fieldgroup, Template, Fields, Page and the InputfieldWrapper method.

      InputfieldWrapper method works great for all the markup stuff, but I just can't wrap my head around what I need to do to save the image to the database.
      Can generate a Field for it (thanks to the api investigations) but not sure what I need to do to link the Inputfield to that. Tried a lot of stuff from various threads, of varying dates without luck.
      Undoubtedly not helped by me not knowing enough.

      Defining Fieldgroup etc through the api seems nice and clean and works great for the images but I can't wrap my head around how/if I can add/append/hook the InputfieldWrapper/InputfieldMarkup stuff I'd like to include on that template as well. Not even sure if it should be where it is on ___install with the Fieldtype stuff or later on . Not getting Tracy errors, just nothing seems to happen.
      If anyone has any ideas or can point me in the right direction, that would be great because at the moment I am stumbling round in the dark.
       
      public function ___install() { parent::___install(); $page = $this->pages->get('name='.self::PAGE_NAME); if (!$page->id) { // Create fieldgroup, template, fields and page // Create new fieldgroup $fmFieldgroup = new Fieldgroup(); $fmFieldgroup->name = MODULE_NAME.'-fieldgroup'; $fmFieldgroup->add($this->fields->get('title')); // needed title field $fmFieldgroup->save(); // Create new template using the fieldgroup $fmTemplate = new Template(); $fmTemplate->name = MODULE_NAME; $fmTemplate->fieldgroup = $fmFieldgroup; $fmTemplate->noSettings = 1; $fmTemplate->noChildren = 1; $fmTemplate->allowNewPages = 0; $fmTemplate->tabContent = MODULE_NAME; $fmTemplate->noChangeTemplate = 1; $fmTemplate->setIcon(ICON); $fmTemplate->save(); // Favicon source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFavicon'; $fmField->label = 'Favicon'; $fmField->focusMode = 'off'; $fmField->gridMode = 'grid'; $fmField->extensions = 'svg png'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Favicon Silhouette source $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeImage"); $fmField->name = 'fmFaviconSilhouette'; $fmField->label = 'SVG Silhouette'; $fmField->notes = 'When creating a silhouette/mask svg version for Safari Pinned Tabs and Windows Tiles, we recommend setting your viewbox for 0 0 16 16, as this is what Apple requires. In many cases, the easiest way to do this in something like illustrator is a sacrificial rectangle with no fill, and no stroke at 16 x 16. This forces the desired viewbox and can then be discarded easily using something as simple as notepad. Easy is good, especially when you get the result you want without a lot of hassle.'; $fmField->focusMode = 'off'; $fmField->extensions = 'svg'; $fmField->columnWidth = 50; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon(ICON); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($fmField); // Create: Open Settings Tab $tabOpener = new Field(); $tabOpener->type = new FieldtypeFieldsetTabOpen(); $tabOpener->name = 'fmTab1'; $tabOpener->label = "Favicon Settings"; $tabOpener->collapsed = Inputfield::collapsedNever; $tabOpener->addTag(MODULE_NAME); $tabOpener->save(); // Create: Close Settings Tab $tabCloser = new Field(); $tabCloser->type = new FieldtypeFieldsetClose; $tabCloser->name = 'fmTab1' . FieldtypeFieldsetTabOpen::fieldsetCloseIdentifier; $tabCloser->label = "Close open tab"; $tabCloser->addTag(MODULE_NAME); $tabCloser->save(); // Create: Opens wrapper for Favicon Folder Name $filesOpener = new Field(); $filesOpener->type = new FieldtypeFieldsetOpen(); $filesOpener->name = 'fmOpenFolderName'; $filesOpener->label = 'Wrap Folder Name'; $filesOpener->class = 'inline'; $filesOpener->collapsed = Inputfield::collapsedNever; $filesOpener->addTag(MODULE_NAME); $filesOpener->save(); // Create: Close wrapper for Favicon Folder Name $filesCloser = new Field(); $filesCloser->type = new FieldtypeFieldsetClose(); $filesCloser->name = 'fmOpenFolderName' . FieldtypeFieldsetOpen::fieldsetCloseIdentifier; $filesCloser->label = "Close open fieldset"; $filesCloser->addTag(MODULE_NAME); $filesCloser->save(); // Create Favicon Folder Name $fmField = new Field(); $fmField->type = $this->modules->get("FieldtypeText"); $fmField->name = 'folderName'; $fmField->label = 'Favicon Folder:'; $fmField->description = $this->config->urls->files; $fmField->placeholder = 'Destination Folder for your generated favicons, webmanifest and browserconfig'; $fmField->columnWidth = 100; $fmField->collapsed = Inputfield::collapsedNever; $fmField->setIcon('folder'); $fmField->addTag(MODULE_NAME); $fmField->save(); $fmFieldgroup->add($tabOpener); $fmFieldgroup->add($filesOpener); $fmFieldgroup->add($fmField); $fmFieldgroup->add($filesCloser); $fmFieldgroup->add($tabCloser); $fmFieldgroup->save(); /////////////////////////////////////////////////////////////// // Experimental Markup Tests $wrapperFaviconMagic = new InputfieldWrapper(); $wrapperFaviconMagic->attr('id','faviconMagicWrapper'); $wrapperFaviconMagic->attr('title',$this->_('Favicon Magic')); // field show info what $field = $this->modules->get('InputfieldMarkup'); $field->name = 'use'; $field->label = __('How do I use it?'); $field->collapsed = Inputfield::collapsedNever; $field->icon('info'); $field->attr('value', 'Does this even begin to vaguely work?'); $field->columnWidth = 50; $wrapperFaviconMagic->add($field); $fmTemplate->fields->add($wrapperFaviconMagic); $fmTemplate->fields->save(); ///////////////////////////////////////////////////////////// // Create page $page = $this->wire( new Page() ); $page->template = MODULE_NAME; $page->parent = $this->wire('pages')->get('/'); $page->addStatus(Page::statusHidden); $page->title = 'Favicons'; $page->name = self::PAGE_NAME; $page->process = $this; $page->save(); } }  
    • By Sebi
      Since it's featured in ProcessWire Weekly #310, now is the time to make it official:
      Here is Twack!
      I really like the following introduction from ProcessWire Weekly, so I hope it is ok if I use it here, too. Look at the project's README for more details!
      Twack is a new — or rather newish — third party module for ProcessWire that provides support for reusable components in an Angular-inspired way. Twack is implemented as an installable module, and a collection of helper and base classes. Key concepts introduced by this module are:
      Components, which have separate views and controllers. Views are simple PHP files that handle the output for the component, whereas controllers extend the TwackComponent base class and provide additional data handling capabilities. Services, which are singletons that provide a shared service where components can request data. The README for Twack uses a NewsService, which returns data related to news items, as an example of a service. Twack components are designed for reusability and encapsulating a set of features for easy maintainability, can handle hierarchical or recursive use (child components), and are simple to integrate with an existing site — even when said site wasn't originally developed with Twack.
      A very basic Twack component view could look something like this:
      <?php namespace ProcessWire; ?> <h1>Hello World!</h1> And here's how you could render it via the API:
      <?php namespace Processwire; $twack = $modules->get('Twack'); $hello = $twack->getNewComponent('HelloWorld'); ?> <html> <head> <title>Hello World</title> </head> <body> <?= $hello->render() ?> </body> </html> Now, just to add a bit more context, here's a simple component controller:
      <?php namespace ProcessWire; class HelloWorld extends TwackComponent { public function __construct($args) { parent::__construct($args); $this->title = 'Hello World!'; if(isset($args['title'])) { $this->title = $args['title']; } } } As you can see, there's not a whole lot new stuff to learn here if you'd like to give Twack a try in one of your projects. The Twack README provides a really informative and easy to follow introduction to all the key concepts (as well as some additional examples) so be sure to check that out before getting started. 
      Twack is in development for several years and I use it for every new project I build. Also integrated is an easy to handle workflow to make outputs as JSON, so it can be used to build responses for a REST-api as well. I will work that out in one section in the readme as well. 
      If you want to see the module in an actual project, I have published the code of www.musical-fabrik.de in a repository. It runs completely with Twack and has an app-endpoint with ajax-output as well.
      I really look forward to hear, what you think of Twack🥳!
      Features Installation Usage Quickstart: Creating a component Naming conventions & component variants Component Parameters directory page parameters viewname Asset handling Services Named components Global components Ajax-Output Configuration Versioning License Changelog
    • By Robin S
      Page Reference Default Value
      Most ProcessWire core inputfield types that can be used with a Page Reference field support a "Default value" setting. This module extends support for default values to the following core inputfield types:
      Page List Select Page List Select Multiple Page Autocomplete (single and multiple) Seeing as these inputfield types only support the selection of pages a Page List Select / Page List Select Multiple is used for defining the default value instead of the Text / Textarea field used by the core for other inputfield types. This makes defining a default value a bit more user-friendly.
      Note that as per the core "Default value" setting, the Page Reference field must be set to "required" in order for the default value to be used.
      Screenshot

       
      https://github.com/Toutouwai/PageReferenceDefaultValue
      https://modules.processwire.com/modules/page-reference-default-value/
×
×
  • Create New...