To participate you must create an account on apostrophenow.com. If you have already done so, click Login.

Apostrophe Manual

Up to the Overview

Installation

There are two ways to get started with Apostrophe. You can start with our sandbox project, which we heartily recommend, or add the apostrophePlugin to your existing Symfony project. The latter only makes sense for experienced Symfony developers whose sites are already well underway. I'll describe both approaches.

Ways to Download the Apostrophe Sandbox Project

Download The Tarball

The easiest way is to just download a tarball of the sandbox project. This tarball is updated nightly from the stable branch of our sandbox. This is a great way to get started, but note that you won't be able to get security and stability fixes just by typing svn update this way.

Check It Out From Subversion

Alternatively you can check it out with subversion:

    svn co http://svn.apostrophenow.org/sandboxes/asandbox/branches/1.4 asandbox

That will check out the 1.4 stable branch, which is suitable for use with both Symfony 1.3 and Symfony 1.4.

If you prefer to live dangerously and use our most bleeding-edge code (as of 6/22 the trunk is currently quite bleeding-edge and we would recommend using the 1.4 branch instead), you can check out the trunk:

    svn co http://svn.apostrophenow.org/sandboxes/asandbox/trunk asandbox

We love it when you do this, because it results in more feedback for us, but you should definitely consider using the stable branch for your client projects. We use the stable branch for our own client projects.

Our Favorite: Copying the Sandbox to Your Own Repository

Checking out the sandbox from svn is a nice way to get started, but you'll soon wonder how to save your own changes when the project is part of our own svn repository. That's why we recommend that you instead copy it to your own repository with svnforeigncopy each time you want to start a new site. That's what we do. With svnforeigncopy you get a copy of the asandbox project in your own svn repository, with the svn:ignore and svn:externals properties completely intact. You don't get the project history, but since 99% of the code is in the externally referenced plugins and libraries, that's really not a big deal. The important thing is that you are still connected to the latest bug-fix updates for our plugin.

This will give you all of the necessary plugins and the ability to svn update the whole shebang with one command.

Here's an example. In this case I have already copied the svnforeigncopy script to my personal ~/bin folder and made it executable with the chmod command. (That assumes ~/bin is in your PATH, which you can adjust in ~/.profile or ~/.bashrc`. If this is all Greek to you, it might be better to download the tarball.)

NOTE: You need svn version 1.5 or better. MacOS X Snow Leopard includes a 1.6.x version of svn, which is plenty good enough. So does Ubuntu Linux. If you don't have svn 1.5 or better, don't worry about it, just install our tarball instead.

This command creates a new svn repository, of course you can use an existing one, such as a beanstalk repository. For more information about svn see the official svn red bean book. Of course you should substitute your own preferred location for /Users/boutell here:

svnadmin create /Users/boutell/myrepo

And this command copies the project from our repository to yours:

svnforeigncopy http://svn.apostrophenow.org/sandboxes/asandbox/branches/1.4 file:////Users/boutell/myrepo/demosite Sites/demosite

Those arguments are the path you're copying from, the path you're copying to, and the local checkout folder where you'll work with the end result (also used as a scratchpad during the copy operation).

You'll be prompted to commit to svn a couple of times (you may need to set your VISUAL environment variable if you have never done so before), and the checkout of symfony in lib/vendor means it'll take a little while to do the final 'update' that brings down the related plugins and Symfony itself. When it's over, though, you have our project cloned in your own repository where you can commit your own changes without losing the connection to the stable branch of our plugin.

If you get an error that says:

Error: no such table: rep_cache

You'll need to disable your svn repository's cache to work around a bug in svn 1.6.5. To do that, just edit myrepo/db/fsfs.conf and add the following line (if it is there but commented out, remove the leading # to activate it):

enable-rep-sharing = false

Thanks to Pablo Godel of ServerGrove for pointing out the issue.

Apache Configuration

Once you have fetched the code by your means of choice, you're ready to configure your testing web server to recognize a new website. Light up the folder asandbox/web as a website named asandbox or whatever suits your needs via MAMP, httpd.conf or whatever your web hosting environment requires. As with any Symfony project you'll want to allow full Apache overrides in this folder. See config/vhost.sample for tips on virtual host configuration for Apache. Make sure the directives in web/.htaccess will be honored by your server.

(Confused about this MAMP stuff? Wondering how you can test websites on your own computer? You really should pick up MAMP if you are on a Mac. Windows and Linux users should consider using XAMPP. These are all-in-one packages with PHP, MySQL, Apache and everything else you need to test real websites on your own computer. You can also install Apostrophe directly on a web hosting account. We just think you'll find web development with Apostrophe and in general oh so much more pleasant if you learn to test on your own computer before uploading things.)

PHP Configuration

There is a php.ini setting that determines whether parameters in URLs are separated by & or by &. Apostrophe currently requires that they be separated by &.

In most web hosting setups, you can add this line to web/.htaccess of your Apostrophe project to ensure that the separator is &:

php_value arg_separator.output &

If PHP directives are not honored in .htaccess files in your hosting setup, you can do this in your php.ini file:

arg_separator.output = "&"

You must also have a reasonable PHP memory_limit setting. We recommend 64 megabytes of memory for PHP:

memory_limit = 64M

A few Linux distributions set unrealistic memory limits on PHP by default. In this case you may get a blank page when accessing Apostrophe sites.

Don't forget to restart Apache if you make changes in php.ini.

Note that without this rule content editing will not work properly in Apostrophe.

Symfony Configuration

Yes, this is a preconfigured sandbox project, but you do have to adjust a few things to reflect reality on your own computer.

Now create the config/databases.yml file, which must contain database settings appropriate to your system. Copy the file config/databases.yml.sample as a starting point:

    cp config/databases.yml.sample config/databases.yml

If you are testing with MAMP the default settings (username root, password root, database name asandbox) may work just fine for you. If you are testing on a staging server you will need to change these credentials.

Also create your properties.ini file:

    cp config/properties.ini.sample config/properties.ini

In Symfony properties.ini contains information about hosts that a project can be synced to, in addition to the name of the project. The sample properties.ini file just defines the name of the project. You'll add information there when and if you choose to sync the project to a production server via project:deploy or our enhanced version, apostrophe:deploy. See the Symfony documentation for more information about that technique.

At this point you're ready to use the checkout of Symfony's 1.4.x stable branch that is included in the project. If you want to use a different installation of Symfony, such as a shared install for many sites (note that only 1.3.x and 1.4.x are likely to work), copy config/require-core.php.example to config/require-core.php and edit the paths in that file.

Next, cd to the asandbox folder and run these commands.

(Windows users: you should remove the web/apostrophePlugin, web/apostropheBlogPlugin, etc. folders first. These are the subfolders in web that end in Plugin. Unix/Linux users don't have to worry about this.)

    ./symfony cc
    ./symfony plugin:publish-assets
    ./symfony doctrine:build --all
    ./symfony doctrine:data-load

This will create a sample database from the fixtures files.

If you prefer, you can pull down our full demo site as an alternative to the somewhat bland fixtures site. Replace the doctrine:data-load command with this one (it's OK to do this if you already did the other command):

    ./symfony apostrophe:demo-fixtures

Note that this task will run for quite a while as media files are included in the download.

Now set the permissions of data folders so that they are writable by the web server. Note that svn does NOT store permissions so you can NOT assume they are already correct:

    ./symfony project:permissions

Our apostrophePlugin extends project:permissions for you to include the data/writable folder in addition to the standard web/uploads, cache and log folders. Handy, isn't it?

If you prefer you can do this manually:

    chmod -R 777 data/a_writable
    chmod -R 777 web/uploads
    chmod -R 777 cache
    chmod -R 777 log

More subtle permissions are possible. However be aware that most "shared hosting" environments are inherently insecure for a variety of reasons. Production Symfony sites should run on a virtual machine of their own, or share a VM only with other sites written by you. So before criticizing the "777 approach," be sure to read this article on shared hosting and Symfony.

Next, build the site's search index for the first time (yes, search is included). It doesn't live in the database so it needs to be done separately. After this, you won't need to run this command again unless you are deploying to a new environment such as a staging or production server and don't plan to sync your content with sfSyncContentPlugin:

    ./symfony apostrophe:rebuild-search-index --env=dev

(You can specify staging or prod instead to build the search indexes for environments by those names. You'll want that later when working on a production server.)

You can now log in as admin with the password demo to see how the site behaves when you're logged in (if you used the apostrophe:demo-fixtures task, the password will be demo). Start adding subpages, editing slots, adding slots to the multiple slot content area... have a ball with it!

Note: For all versions of the demo site, the login is `admin` and the password is `demo`.

The Hard Way: Adding apostrophePlugin To An Existing Site

Those who installed the sandbox just now can skip right over this section.

Installing the sandbox is the easy way to install Apostrophe. The notes that follow assume you're doing it the hard way, without starting from the asandbox project.

Begin by installing the following Symfony plugins into your Symfony 1.3/1.4 project:

  • sfJqueryReloadedPlugin
  • sfDoctrineGuardPlugin
  • sfDoctrineActAsTaggablePlugin
  • sfWebBrowserPlugin
  • sfFeed2Plugin
  • sfSyncContentPlugin (recommended but not required)
  • And of course, apostrophePlugin

We strongly encourage you to do so using svn externals. If you are using that approach you will need to be sure to create the necessary symbolic links from your projects web/ folder to to the web/ folders of the plugins that have one. For best results use a relative path:

    cd web
    ln -s ../plugins/apostrophePlugin/web apostrophePlugin
    # Similar for other plugins required

The search features of the plugin rely on Zend Search, so you must also install the Zend framework. The latest version of the minimal Zend framework is sufficient. If you choose to install this system-wide where all PHP code can easily find it with a require statement, great. If you prefer to install it in your Symfony project's lib/vendor folder, you'll need to modify your ProjectConfiguration class to ensure that require statements can easily find files there:

    class ProjectConfiguration extends sfProjectConfiguration
    {
      public function setup()
      {
        // We do this here because we chose to put Zend in lib/vendor/Zend.
        // If it is installed system-wide then this isn't necessary to
        // enable Zend Search
        set_include_path(
          sfConfig::get('sf_lib_dir') .
            '/vendor' . PATH_SEPARATOR . get_include_path());
        // for compatibility / remove and enable only the plugins you want
        $this->enableAllPluginsExcept(array('sfPropelPlugin'));
      }
    }

Create an application in your project. Then create a module folder named a as a home for your page templates and layouts (and possibly other customizations):

    mkdir -p apps/frontend/modules/a/templates

The CMS provides convenient login and logout links. By default these are mapped to sfGuardAuth's signin and signout actions. If you are using sfShibbolethPlugin to extend sfDoctrineGuardPlugin, you'll want to change these actions in apps/frontend/config/app.yml:

    all:
      sfShibboleth:
        domain: duke.edu
      a:
        actions_logout: "sfShibbolethAuth/logout"
        actions_login: "sfShibbolethAuth/login"

You can also log in by going directly to /login. If you don't want to display the login link (for instance, because your site is edited only you), just shut that feature off:

    all:
      a:
        login_link: false

You will also need to enable the Apostrophe modules in your application's settings.yml file. Of course you may need other modules as well based on your application's needs:

    enabled_modules:
      - a
      - aSync
      - aNavigation
      - aMedia
      - aMediaBackend
      - aRichTextSlot
      - aTextSlot
      - aRawHTMLSlot
      - aSlideshowSlot
      - aVideoSlot
      - aImageSlot
      - aButtonSlot
      - aPDFSlot
      - aFeedSlot
      - sfGuardAuth
      - aUserAdmin
      - aGroupAdmin
      - aPermissionAdmin
      - sfGuardPermission
      - taggableComplete
      - aNavigation
      - default
      - aAdmin

Apostrophe edits rich text content via the FCK editor. A recent version of FCK is included with the plugin. However you'll need to enable FCK in your settings.yml file, as follows:

    all:
      rich_text_fck_js_dir:   apostrophePlugin/js/fckeditor

Disabling Output Escaping

By default, a new Symfony 1.4 project escapes all output that is emitted in templates. Apostrophe's strategy is to store valid UTF-8 encoded HTML to begin with, addressing this issue in validators. Currently you must disable output escaping in settings.yml, otherwise Apostrophe slots will not work properly:

  all:
      # Output escaping settings
      escaping_strategy:      false

(We are looking into ways to support either setting so that Apostrophe does not force you to choose the same strategy for your own Symfony code. If we can do that without too much overhead, we will.)

Now, load the fixtures for a basic site. Every site begins with a home page with all other pages being added as descendants of the home page:

    ./symfony doctrine:build --all
    ./symfony doctrine:data-load

Note: if you are adding apostrophePlugin to an existin site you probably don't want to delete your other tables and start over! You can do:

    ./symfony doctrine:build --all-classes --sql

To build the model classes and to build the SQL code that would be sufficient to recreate your database. Then look in data/sql/schema.sql for the CREATE TABLE statements for tables beginning with the a_ prefix.

Ideally you would use Doctrine's migration schema diff task instead. Unfortunately there is currently a bug in Symfony and Doctrine that prevents successful use of this feature with tables that use inheritance. See Symfony bug 7272 for more information and patches if you are interested in pursuing that approach. It's probably easier to just locate the CREATE TABLE statements.

You will also want to load the fixtures for the apostrophePlugin or, depending on your needs, edit them to suit your purposes better first. You can do so without clobbering your existing database:

./symfony doctrine:data-load --append plugins/apostrophePlugin/data/fixtures/seed_data.yml

In particular you must have a home page and the hidden /admin and /admin/media engine pages.

Also see the fixtures provided with the sandbox project for strongly recommended (but not mandatory) permissions and groups settings.

.htaccess Rules For Media

The media module of Apostrophe uses carefully designed URLs to allow images to be served as static files after they are generated for the first time. This is done at the Apache level to maximize performance: PHP (and therefore Symfony) don't have to get involved at all after the first time an image is rendered at a particular size.

The following special .htaccess rules are required to enable this. These should be copied to your .htaccess file after the RewriteBase / rule, if you are using one, but before any other rules.

    ###### BEGIN special handling for the media module's cached scaled images
    # If it exists, just deliver it
    RewriteCond %{REQUEST_URI} ^/uploads/media_items/.+$
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule .* - [L]
    # If it doesn't exist, render it via the front end controller
    RewriteCond %{REQUEST_URI} ^/uploads/media_items/.+$
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
    ###### END special handling for the media module's cached scaled images

Routing Rules

By default Apostrophe will map CMS pages to URLs beginning with /cms:

    /cms/pagename

And leave all other URLs alone. This is appropriate if the CMS is a minor part of your site. If the CMS is the main purpose of your site, shut off the automatic registration of the route above in app.yml:

    a:
      routes_register: false

And register these as the LAST rules in your application's routing.yml file instead:

    # A default rule that gets us to actions outside of the CMS.
    # Note that you can't have regular CMS pages with a slug beginning with /admin
    # on an Apostrophe site. At some point we'll make this reserved prefix more
    # configurable. 
    default:
      url:   /admin/:module/:action/*
    # A homepage rule is expected by a and various other plugins,
    # so be sure to have one
    homepage:
      url:  /
      param: { module: a, action: show, slug: / }
    # Put any routing rules for other modules and actions HERE,
    # before the catch-all rule that routes URLs to the
    # CMS by default.
    # Must be the last rule
    a_page:
      url:   /:slug
      param: { module: a, action: show }
      requirements: { slug: .* }

Thanks to Stephen Ostrow for his help with these rules.

You can change the a_page rule, prefixing the page slug with anything you wish, but you must have such a rule and it must be named a_page. Otherwise Apostrophe engines, including the built-in media repository functionality and media slots, will not work.

layout.php Requirements

Apostrophe's non-CMS pages, such as the "reorganize" feature, the user admin feature and the media repository, expect a layout that offers certain overridable Symfony slots, in particular the a-subnav slot. The media repository overrides this slot to offer media navigation links instead of a list of subpages. If your application layout does not offer such a slot to override, the media repository will be missing some of its interface.

Take a close look at modules/a/templates/layout.php and check out the way we've provided the ability for page templates to override various parts of the layout via Symfony slots. If you experience missing bits of the UI with your own layout, make sure you offer the same slots at appropriate points.

** Prior to Apostrophe 1.0.7 ** the media repository in particular defaults to using a built-in layout that is not really suitable for its current markup. You can fix this with an app.yml setting which is also found in the sandbox project:

all:
  aMedia:
    use_bundled_layout: false

Beginning in Apostrophe 1.0.7 this is no longer necessary.

Styling Requirements

The user interface will be essentially complete at this point, but you may notice a few areas in the media repository where the look and feel is a bit too austere unless you borrow elements from the sandbox project's main.css file or apply some styles of your own. In fact in Apostrophe 1.1 we will be migrating toward moving more of the hard-to-override, site-design-specific CSS from a.css to the main.css file of the sandbox project. So you may want to refer to that file as a reference.

Set Permissions

In Symfony, the cache and web/uploads folders are always world-writable so that the web server can store files. Apostrophe adds one more such folder, data/a_writable. This folder is used for files that should be writable by the web server but not directly accessible via a URL. This folder is used for search indexes and other data that does not live in the database.

You can set up this folder yourself, but it's more convenient to use Symfony's project:permissions task, which apostrophePlugin enhances to handle this folder:

./symfony project:permissions

Performance Optimization

By default, Apostrophe is configured to provide good navigation and reasonable performance without running out of memory, even if your site has thousands of pages.

If you are certain that your page will never have more than about 500 pages, you can improve performance somewhat with the following app.yml setting:

all:
  a:
    many_pages: false

When you use this setting, Apostrophe will fetch the entire page tree with a very efficient direct SQL query and reuse that information for every navigation element that appears in the page. This is a good choice until the page tree becomes large, at which point it is more efficient to fetch just the necessary information for each navigation element, even though this requires a few extra SQL queries. On a very large site, it is essential that you leave this option set to true (the default setting). For instance, on a site with 8,000 pages, setting this option to false can result in page loads that require 64MB of memory. So it should be used only on sites that are small by design.

Clear the Cache and Get to Work!

No Symfony developer will be shocked to hear that you need to clear your Symfony cache at this point:

./symfony cc

We're done installing Apostrophe! On to the editor's guide, which briefly explains how to edit content with Apostrophe- briefly because it is so much more fun to simply use it.

Continue to the Editor's Guide

Up to the Overview