Extend, not replace, the index() method for ContentController

Silverstripe Version: 4.x

I have written an extension to minify html:


namespace myNamespace;

use SilverStripe\Core\Extension;
use SilverStripe\Control\HTTPRequest;

class HTMLMinificationExtension extends Extension
{

	public function index(HTTPRequest $request)
	{
		$html = $this->owner->render();
		$html = preg_replace(array('/<!--(.*)-->/Uis',"/[[:blank:]]+/"),array('',' '),str_replace(array("\n","\r","\t"),'',$html));
		return $html;
	}

}

and applied to the ContentContoller class in a YAML:

---
Name: HTMLMinification
---
SilverStripe\CMS\Controllers\ContentController:
  extensions:
    - myNamespace\HTMLMinificationExtension

The above works as expected on all controllers that extend ContentController, unless they have defined their own index() method. For example the BlogController from silverstripe/blog module.

Question: How can I augment the ContentController->index() method so it is not replaced by other modules?

Feel free to tell me if this is not the correct way to go about minification with SS!

Cheers,
Olly

You might be better off using a middleware for this, rather than doing it in a controller. That way you can just catch the full output of all the controllers, etc. without worrying what might override your code:

Thanks @Tim that pointer to Middlewares is just what I needed!

I thought I was barking up the wrong tree using index()…

For others that may end up here looking for an HTML minification solution, here’s the the code I ended up using:

<?php

	namespace myNamespace;

	use SilverStripe\Control\Middleware\HTTPMiddleware;
	use SilverStripe\Control\HTTPRequest;

	class HTMLMinificationMiddleware implements HTTPMiddleware
	{

	    public function process(HTTPRequest $request, callable $delegate)
	    {

	        $response = $delegate($request);

	        $responseBody = $response->getBody();

	        // you may want to filter out requests to admin pages here and just return the unmodifed response
	        // return $response;
	        
	        //apply your chosen minification method here - here is a basic preg_replace to get started
	        $responseBody_Minified = preg_replace(array('/<!--(.*)-->/Uis',"/[[:blank:]]+/"),array('',' '),str_replace(array("\n","\r","\t"),'', $responseBody));

	        return $response->setBody($responseBody_Minified);
	    }

	}

Applied globally in app.yml:

---
Name: myrequestprocessors
After:
  - requestprocessors
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Control\Director:
    properties:
      Middlewares:
        HTMLMinificationMiddleware: %$myNamespace\HTMLMinificationMiddleware
1 Like

Since I needed it for a project, I’ve created a module to do this using the Voku minifier:

Just in case anyone needs something!

1 Like