Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preventing Assetic from rewriting each time #433

Open
Zxurian opened this issue May 24, 2013 · 8 comments
Open

Preventing Assetic from rewriting each time #433

Zxurian opened this issue May 24, 2013 · 8 comments

Comments

@Zxurian
Copy link

Zxurian commented May 24, 2013

So i'm using the following code to setup workers with collections, and then write them to a publically accessible drectory, then passing the resulting file to my view controller so that the files can be included in the head of my templates.

The problem is that it's running the assets through the filters every time, not just on changes (which is what I understood the CacheBustingWorker was supposed to prevent).

I'm running on the theory that I'm doing something wrong, but can't figure out where I'm going astray.

Is there a method I can run to to check if there's changes on the assets to see if there's any changes? and if none, just returns the resulting file names instead of rewriting them each time?

        // Prepare FilterManager with all filters that will be used
        $FilterManager = new FilterManager();
        $FilterManager->set('scss', new ScssphpFilter());
        $FilterManager->set('cssmin', new MinifyCssFilter());
        $FilterManager->set('jsmin', new JSMinFilter());

        $AssetManager = new AssetManager();
        // Prepare the AssetManager with all core assets
        $AssetManager->set('coreCss', new AssetCollection(array(
            new FileAsset('public/vendor/bootstrap/css/bootstrap.min.css'),
            new FileAsset('public/vendor/bootstrap/css/bootstrap-responsive.min.css'),
            new FileAsset('module/application/assets/css/fonts.css'),
            new FileAsset('module/application/assets/css/main.scss'),
        )));
        $AssetManager->set('coreJs', new AssetCollection(array(
            new FileAsset('public/vendor/modernizr/modernizr-2.6.2.js'),
            new FileAsset('public/vendor/respond/respond.min.js'),
            new FileAsset('public/vendor/jquery/jquery-1.9.1.min.js'),
            new FileAsset('public/vendor/bootstrap/js/bootstrap.min.js'),           
        )));

        // Add the controller specific assets
        $controllerCss = new AssetCollection();
        foreach ($this->assets['css'] as $file) {
            $controllerCss->add(new FileAsset($file));
        }
        $AssetManager->set('controllerCss', $controllerCss);
        $controllerJs = new AssetCollection();
        foreach ($this->assets['js'] as $file) {
            $controllerJs->add(new FileAsset($file));
        }
        $AssetManager->set('controllerJs', $controllerJs);

        // Setup factory to create the assets with cachebusting
        $factory = new AssetFactory('/');
        $factory->setAssetManager($AssetManager);
        $factory->setFilterManager($FilterManager);
        $factory->setDebug(true);
        $factory->addWorker(new CacheBustingWorker(CacheBustingWorker::STRATEGY_CONTENT));
        //$factory->addWorker(new CacheBustingWorker(new LazyAssetManager($factory)));

        // Create the assets
        $coreCss = $factory->createAsset(array(
            '@coreCss',         
        ), array(
            'scss',
            '?cssmin',                  
        ));

        $controllerCss = $factory->createAsset(array(
            '@controllerCss',           
        ), array(
            'scss',
            '?cssmin',
        ));

        $coreJs = $factory->createAsset(array(
            '@coreJs',
        ), array(
            '?jsmin',
        ));

        $controllerJs = $factory->createAsset(array(
            '@controllerJs',            
        ), array(
            '?jsmin'
        ));

        // load last modified times
        $lastModifiedData = $this->db->query('SELECT * FROM `cache`', array()); $lastModified = array();
        foreach ($lastModifiedData as $lmd) {
            $lastModified[$lmd['cache_name']] = $lmd['last_modified'];
        }

        // setup writer
        $writer = new AssetWriter('public/cache');

        $coreCssPath = $coreCss->getTargetPath();
        if (!isset($lastModified[$coreCssPath]) || strtotime($lastModified[$coreCssPath]) < $coreCss->getLastModified()) {
            $writer->writeAsset($coreCss);
            rename(getcwd().'/public/cache/'.$coreCssPath, getcwd().'/public/cache/'.$coreCssPath.'.css');
            $this->db->query('INSERT INTO `cache` (`cache_name`, `last_modified`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `last_modified` = ?', array($coreCssPath, date('Y-m-d H:i:s'), date('Y-m-d H:i:s')));
        }

        $controllerCssPath = $controllerCss->getTargetPath();
        if (!isset($lastModified[$controllerCssPath]) || strtotime($lastModified[$controllerCssPath]) < $controllerCss->getLastModified()) {
            $writer->writeAsset($controllerCss);
            rename(getcwd().'/public/cache/'.$controllerCssPath, getcwd().'/public/cache/'.$controllerCssPath.'.css');
            $this->db->query('INSERT INTO `cache` (`cache_name`, `last_modified`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `last_modified` = ?', array($controllerCssPath, date('Y-m-d H:i:s'), date('Y-m-d H:i:s')));
        }

        $coreJsPath = $coreJs->getTargetPath();
        if (!isset($lastModified[$coreJsPath]) || strtotime($lastModified[$coreJsPath]) < $coreJs->getLastModified()) {
            $writer->writeAsset($coreJs);
            rename(getcwd().'/public/cache/'.$coreJsPath, getcwd().'/public/cache/'.$coreJsPath.'.css');
            $this->db->query('INSERT INTO `cache` (`cache_name`, `last_modified`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `last_modified` = ?', array($coreJsPath, date('Y-m-d H:i:s'), date('Y-m-d H:i:s')));
        }

        $controllerJsPath = $controllerJs->getTargetPath();
        if (!isset($lastModified[$controllerJsPath]) || strtotime($lastModified[$controllerJsPath]) < $controllerJs->getLastModified()) {
            $writer->writeAsset($controllerJs);
            rename(getcwd().'/public/cache/'.$controllerJsPath, getcwd().'/public/cache/'.$controllerJsPath.'.css');
            $this->db->query('INSERT INTO `cache` (`cache_name`, `last_modified`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `last_modified` = ?', array($controllerJsPath, date('Y-m-d H:i:s'), date('Y-m-d H:i:s')));
        }

        // add paths to view model
        $view = $e->getParam('application')->getMvcEvent()->getViewModel();
        $view->coreCssPath = $coreCssPath.'.css';
        $view->controllerCssPath = $controllerCssPath.'.css';
        $view->coreJsPath = $coreJsPath.'.js';
        $view->controllerJsPath = $controllerJsPath.'.js';
@stof
Copy link
Collaborator

stof commented May 24, 2013

CacheBustingWorker is not about preventing running assetic filters. It is about changing the generated name when the content changes, to bust the browser cache (thus allowing to use cache headers far in the future)

@Zxurian
Copy link
Author

Zxurian commented May 24, 2013

thank you. So I should write my own method about testing if file contents have changed before sending the assets to the writer?

Can the method that generates the file name be called separately from writing the file so I can still pass it?

@stof
Copy link
Collaborator

stof commented May 24, 2013

@Zxurian the check if it has changed would be comparing $assetManager->getLastModifiedTime($asset) with the time where it has been dumped previously.
The method that generate the filename has nothing to do with the check. It simply add a hash in the filename, and one of the data used to compute the hash is the last modified time

@mpdude
Copy link
Contributor

mpdude commented May 24, 2013

@stof just a gut feeling, but at least for the "deep" mtime that would still apply filters, not?

And you have to use the LazyAssetManager, the simple one does not provide that method.

@Zxurian
Copy link
Author

Zxurian commented May 25, 2013

@mpdude I can verify that calling ->getLastModified() doesn't apply the filters, just returns the most recent last modified date of files in the collection.

Thanks for the heads up. I've modified my code accordingly, however the names being generated aren't unique to the collection. (getting names via $Asset->getTargetPath()) How can I make the names unique to the content that's in them? (original post updated with new code)

@Zxurian
Copy link
Author

Zxurian commented May 25, 2013

I take it back @mpdude , I went through the source, and using the CacheBustingWorker for content does in fact base it off the ->dump() method, which is post-filter, I thought it was based on pre-filtered content, so I've switched to modification time.

Last problem is that it's not generating new asset names based on the input file names/paths. I'm substituting my own renaming funciton for the time being, but I was under the impression that the name generated was supposed to be unique based on the input assets.

@mpdude
Copy link
Contributor

mpdude commented May 25, 2013

Are you using 1.0 or the 1.1 branch?

@Zxurian
Copy link
Author

Zxurian commented May 30, 2013

I've been pulling from the master branch, but haven't updated in a while.
Just for clarification, should using the CacheBustingWorker for content perform the check before or after the assets have been put through the filters?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants