I manage a growing number of symfony-based Intranet apps that share a common look-and-feel. I use the same stylesheet and images on them all, and it I am nervous every time I make Yet Another Copy of the same files, knowing that I’m duplicating them and causing trouble for myself.
Also, as I wrote in my post about custom error pages, I have error pages set up for each, and I hate copying them. So I have invested some time into building a plugin containing the visual assets and the customized error pages, so that it’s easier to keep them uniform across all the apps I work on, and so that it will be that much quicker to build new projects.
I don’t think anyone outside my company will want my plug-in, but these instructions will hopefully be useful for anyone who wants to do the same thing.
These instructions are for symfony 1.1 but they should apply equally to 1.0 and 1.2.
Plugin organization
Here are the files and directories in my plugin:
plugins/myThemePlugin/
config/
view.yml
modules/
default/
config/
view.yml
templates/
disabledSuccess.php
error404Success.php
README
web/
css/
mystyles.css
myerrors.css
mymain.css
errors/
error500.php
unavailable.php
images/
my_swoop.jpg
bg_sfTAlert.jpg
bg_sfTLock.jpg
bg_sfTMessage.jpg
indicator.gif
tall_gradient.jpg
Using svn:externals to install the plugin in each symfony project
I only want one copy of this thing, with version control, so I use svn:externals (for my other plugins too ).
$ svn propget svn:externals plugins myThemePlugin/ https://mysvnserver.com/svn/web/myThemePlugin sfGuardPlugin/ http://svn.symfony-project.com/plugins/sfGuardPlugin/branches/1.1/ $ svn up
Publishing the assets
The chapter on plugins in the The Definitive Guide to symfony explains:
Web assets (images, scripts, style sheets, etc.) are made available to the server. When you install a plug-in via the command line, symfony creates a symlink to the project
web/directory if the system allows it, or copies the content of the moduleweb/directory into the project one. If the plug-in is installed from an archive or a version control repository, you have to copy the plug-inweb/directory by hand (as theREADMEbundled with the plug-in should mention).
As I showed above, I prefer to use svn:externals for my plugins, so this is a bit of a problem for me. Also, I develop on Windows (with XAMPP and Cygwin), so the more elegant symlink solution is not an option. Symfony 1.2 has a task called plugin:publish_assets that makes the copies, but that messes up my version control strategy. SO: I am going to use svn:externals to get the web assets from my plugin too.
$ svn propset svn:externals "myThemePlugin https://my_svn_server/svn/web/myThemePlugin/web/" web $ svn propget svn:externals web myThemePlugin https://my_svn_server/svn/web/myThemePlugin/web/ $ svn up
This lets me keep the plugin in its own repository. You could get a similar effect by just checking out the files, but it would clutter up the SVN for your main project.
The end result: I have one copy of the web assets in the SVN repository, but they’re checked out twice into each project (once under plugins/myThemePlugin/web and once under web/myThemePlugin).
view.yml files
Now the overall view.yml file in plugins/myThemePlugin/config/ sets stylesheets for my whole project:
default:
stylesheets:
- /myThemePlugin/css/main: { position: last }
- /myThemePlugin/css/bannerhealth: {position: last}
- %SF_ADMIN_WEB_DIR%/css/main
- %SF_CALENDAR_WEB_DIR%/skins/aqua/themeAnd I have another one to apply some additional stylesheets to my error pages:
error404Success:
metas:
title: 404 Not Found
stylesheets:
- /sf/sf_default/css/screen.css
- /sf/sf_default/css/ie.css
- /myThemePlugin/css/errors: {position: last}
disabledSuccess:
metas:
title: Temporarily Unavailable
stylesheets:
- /sf/sf_default/css/screen.css
- /sf/sf_default/css/ie.css
- /myThemePlugin/css/errors: {position: last}relative image paths in stylesheets and error pages
I use relative paths in my stylesheets (served out of myprojecturl/myThemePlugin/css/) so they can find the images (myprojecturl/myThemePlugin/images/):
background-image: url(../images/tall_gradient.jpg);
I’d do the same if my error templates (like plugins/myThemePlugin/modules/default/templates/error404Success.php) used images, but they don’t.
The pages in plugins/myThemePlugin/web/errors (which are installed via svn:externals now in web/myThemePlugin/errors) are used when things are so broken symfony can’t build template pages, so they have full HTML structure, including full stylesheet tags:
<?php $path = '..'; ?> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $path ?>/../sf/sf_default/css/screen.css" /> <!--[if lt IE 7.]> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $path ?>/../sf/sf_default/css/ie.css" /> <![endif]--> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $path ?>/css/main.css" /> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $path ?>/css/bannerhealth.css" /> <link rel="stylesheet" type="text/css" media="screen" href="<?php echo $path ?>/css/errors.css" />
Apache error page configuration
Finally, I tell Apache to use my customized error pages for errors in this project.
<Directory "/path/to/myproject/web"> ErrorDocument 404 /myproject/default/error404 ErrorDocument 500 /myproject/bhThemePlugin/errors/error500.php </Directory>
There we go! Now I have a lot less to do each time I make a new app; all the pretty stuff is in my plugin, and there aren’t any surprisingly brown symfony pages to throw off any users.
What do you think? Any errors or ommissions or problems?
No comments yet.