Improved Assetmanager

Hello - I currently have some problems with assetmanager. And want to share my thoughts what can be done to improve it…

Please don’t take my arguments as plain critic but as constructive ideas where improvements might be needed

Issue 1:

Every file will exist twice - I propose to add a (filesystem-)link option

Issue 2:

folderhashes are relative to the filesystem root and not the project root… since those hashes aren’t very descriptive it can be very anoying to find the way through many directories with the same content

also when I put my whole project folder to my webspace… I won’t delete all the published assets cause the webserver has a different folderstructure and therefore different hashes

so instead using /var/www/yii/project/protected/assets as hash… use protected/assets as hash…

Issue 3:

doesn’t work together with safe_mode … please don’t answer me with disable it or change the host… yii is working perfectly well with safe_mode besides that assetmanager… my idea was to add a ftp-interface which can circumvent the safe_mode restrictions… but also if issue2 can be solved it wouldn’t be that problematic anymore

Issue 4:

changing some css/image always results in an additional rm -rf assets command… If you have to do it often you know how annoying this can get…

Issue 5:

folderhashes aren’t readable… i would propose some more information maybe something like

user_assets_1234abc for protected/modules/user/assets and shrinking the foldernames to a general maximum of X chars so that the foldernames won’t get too long…


I hope some ideas can be picked up for an improved version or maybe an extension…

In general I like the assetmanager… but besides using it together with extensions it I don’t want to use it… my own projects currently all have a css directory in it’s root where the assetmanager instead could do the job…

I wonder if I am alone with those issues…

But I can show you what is in my mind… I took the basic CAssetManager and removed everything which isn’t used by my extensions or me… (especialy those parameter for publish)

to configure it following is needed:


    'components'=>array(

       'assetManager'=>array(

           'class'=>'application.extensions.SimpleAssetManager',

           'strategy'=>'copy',

       ),

and the file inside extensions

there are several strategies:

copy is that already existing function where we just copy everything in the assetfolder

link will add a symlink to the assetfolder inside the root

keep or safe_mode won’t copy the directories - you have to enably the access to the assets dir inside your .htaccess (for testing i just removed the deny all rule)

then there exists a public attribute which can force a copy even if the directory already exists

when i should continue working on it, i think it should be standarized, that the foldername of all assets which should get published should be "assets" and nothing else… and also only folders should be publishable… i see no sense in publishing single files - this makes only the code complicated

edit:

to follow the first post:

issue1: closed with link or keep strategy

issue2: partially closed… i forgot to remove the root-path for the framework directory but project assets now won’t take the rootpath

issue3: closed

issue4: closed

issue5: todo

Mh, I don’t want to offend you, but are you sure you use the asset manager the way it’s meant to be used? All these hashes in the assets folder shouldn’t interest you, because you should never have to deal with them.

About the issues…

#1: True, the files will exist twice. But is this a problem? The linking strategy might cause problems under windows.

#2: As mentioned, you shouldn’t care about the pathes. You also don’t need to copy published assets to the server, because they will be published on demand.

#3: Could you please explain that? I don’t know what problems arise with safe_mode, maybe this is s.th. that could be improved.

#4: As long as the application is in debug mode, modified assets should be republished automatically as far as I can remember. I guess the asset manager checks the files timestamps.

#5: same as #2

Ben, do you know what ‘safe_mode’ means? :)

References:

http://php.net/manua...s.safe-mode.php

http://kb.mediatempl…nd+work-arounds

One of the issues is that when you do a ‘mkdir’, you cannot remove the directory you just created, because the UID is not going to match.

(See the first reference)

Yes, it’s going to be deprecated soon. :)

But a lot of shared hosting out there are using it…

Where does the asset manager remove a dir?

I have no idea if it does or not. :)

I’ll let the OP explain the issues with having safe_mode turned on.

I just thought I’d add to the topic by answering (part of) Ben’s questions number 3. ;)

Well, the AssetManager does not delete anything, AFAIK. Besides that i agree with Ben.

I think, creating a custom asset manager is the right way to go - you can publish it as an extension if you manage to make it work.

#1: True, the files will exist twice. But is this a problem? The linking strategy might cause problems under windows.

  • perhaps memory is cheap… but in my opinion it just isn’t nice to have everything twice… (later I give also an example)

#2: As mentioned, you shouldn’t care about the pathes. You also don’t need to copy published assets to the server, because they will be published on demand.

  • you didn’t understood my point… when i move a directory to another location it will create totally different hashes… if you can’t explain me why this is a good idea, then it is a bad idea… for example developing locally and then pushing just everything including the assets dir (this would make sense if safe_mode is on cause then it don’t need to recreate the files inside assets)

the script just doesn’t care about the already existing assets cause the absolute path’s have changed

#3: Could you please explain that? I don’t know what problems arise with safe_mode, maybe this is s.th. that could be improved.

  • mainly the copyfunction is affected by this… a simple workaround for the current existing assetmanager would be for example to rename the assets to that names described in #2 and then uploading them

#4: As long as the application is in debug mode, modified assets should be republished automatically as far as I can remember. I guess the asset manager checks the files timestamps.

  • you can add a parameter to publish() where it will force the recreation… but debug mode isn’t respected…

and next note: file timestamps are only respected if you publish a single file not a whole folder

#5: same as #2

  • but I want to have it as feature cause i don’t like that the framework is hiding my stuff (giving it strange names means hiding for me)… for example looking at my webpage and some helpertool tells me that file style.css in abcd12345 has some broken code inside… now tell me how i’m supposed to find the right style.css (which is perhaps in nearly every assetfolder represented) without reading the file and comparing the contents with your assets inside your protected folder

… this example also goes for #2 and #1 where you see the problem of having everything multiple times

about linking and windows: i’m not sure how it will work there… but if it is configurable this isn’t a big problem

also I just want to ask you how much does the assetmanager actually help you in developement-process? how much of you don’t use the assetmanager for files which are changing often or for large amounts of files (for example a static gallery of pictures ~100mb … having them twice just makes your hoster rich cause you have to buy a new plan)

currently the assetmanager is helping me only with extensions where it is nice that those files are hidden from my eyes

If you all are comfortable with the current assetmanager there is no problem for me… For me the current implementation just has too many flaws and I thought it would be generally a good idea to increase the Version we have inside the core

Maybe you have a wrong idea what the asset manager is for. It’s not meant to publish every CSS or image that you use on your webpage. You can include them like you always did when writing a web app. Put them into /css or /images and link to them as usual (maybe use the bu() helper to make sure URLs are correct in case you use friendly URLs).

But the asset manager is very important as the framework folder (and also the extensions) can be put completely outside the web folder. So to get public access to e.g. the CSS for a gridview or an icon that comes with an extension, these files need to be copied somewhere into the web folder. That’s what the asset manager does for you.

The cryptic directory names are created as a hash from file path + Yii version. This is done to

a ) make sure that expired asset files from previous Yii versions will not collide with the up-to-date files

b ) to allow to publish the same filename twice without collision (e.g. different extensions could use style.css). Since another source directory leads to another hash, such a collision can never happen.

So the asset folder should better be seen as a temporary public folder with volatile content. It doesn’t matter wether the paths are the same on your local machine and the production server - you won’t upload your local asset folder anyway.

Yii’s strength is to develop all pages very modular… therefore i am also creating extensions and modules which will need css and i also have to debug them… so I’m not missusing it… And for exactly this scenario when the website should become very modularized the assetmanager is a very good idea… I’m not saying that the assetmanager is bad… but i think the assetmanager needs some improvements to get that style of developement more comfortable

I know the reasons and they are good - but I think it should be at least configurable that the pathnames aren’t absolute… for example it would already be unique if all files inside the yii-framework folder will start at framework/bla/blub/assets and not /mnt/sda1/framework/bla/blub/assets.

All local project folders could start at protected/modules/bla/assets.

Okay you can come and say, what happens if we have a 3rd framework with exactly the same structure… that might bring problems… but then the framework just can go into a framework2 folder and it’s fine…

Or maybe only relative paths will be taken if the root-dir of a project has registered at yii… if not the absolute path can be used…


And I would like to upload my assets if safe mode is on… also why you think it is important to forbid this?..

I don’t mind if you think you don’t need it… but I don’t see your arguments why it should be exactly like this and can’t have another aproach…

Oh, I’m sorry, i’m not against another approach, i just tried to explain, why i think the current implementation is like it is. If you find a better way to address the issues a+b above - why not? You already started to create your own implementation. If it alleviates the problems with safe mode, that’s great! And even if it doesn’t make its way into the framework it would give a great extension.

I am most probably going to run into these issues myself due to one of my sites being hosted on a cheap shared host with safe mode on.

I think an alternative safe_mode compatible assetmanager would be an awesome extension.

And it would broaden the reach of Yii because you could use it even on lesser hosts.

It’s a good idea. Not in Yii core, but as an extension.

Safe mode is deprecated in PHP 5.3 anyway (IIRC), so it wouldn’t be future proof to build that into Yii. IMO. ;)

I have posted this ticket on 8th Oct:

http://code.google.com/p/yii/issues/detail?id=1658

just want to note here, that it got fixed with: http://code.google.com/p/yii/source/detail?r=2599

To fix it just add to your config/main.php:

‘components’=>array(

‘assetManager’=>array(

‘linkAssets’=>true,

),

),


edit: small correction I found that, when publishing single files safe mode will be again in effect

to fix it you have to edit CAssetManager or extend it:


if(is_file($src))

{

    $dir=$this->hash($hashByName ? basename($src) : dirname($src));

    $fileName=basename($src);

    $dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;

    $dstFile=$dstDir.'_'.$fileName; //change on this line

    if($this->linkAssets)

    {

        if(!is_file($dstFile))

        {

            //if(!is_dir($dstDir))

            // {

            //  mkdir($dstDir);

            //  @chmod($dstDir,0777);

            // }

            symlink($src,$dstFile);

         }

     }

     else if(@filemtime($dstFile)<@filemtime($src) || $forceCopy)

     {

     //if(!is_dir($dstDir))

     //{

     //  mkdir($dstDir);

     //  @chmod($dstDir,0777);

     //}

     copy($src,$dstFile);

     }

     return $this->_published[$path]=$this->getBaseUrl()."/".$dir."_".$fileName; //change on this line