Skip to main content

Senior Web Engineer. Open web / music. Remote DJ. Tall Dutch guy. #3million

micro.blog/sander

svandragt

mixcloud.com/cloudseer

 

Removing index.php from SilverStripe sites

If your website has mod_rewrite enabled but the URL's generated by SilverStripe still contain 'index.php' then SilverStripe is unable to detect mod_rewrite. Adding the following line to /mysite/_config.php will address the issue (Thanks DsX):

Director::setBaseURL('/'); // fixed index.php in the URL's

 

Automatic crash reporting using FogBugz for PowerShell

This morning I integrated our PowerShell processes into FogBugz by writing a small module that submits occurrences of all errors to BugzScout. You might want to do something similar so I did this write-up.

Broadly it works similar to BugzScoutLogWriter that I developed previously for integration with SilverStripe CMS. In this case however, we need to do the following things:

  1. Set the script to stop on all errors so they can be trapped instead of ending the execution of the script.
  2. Capture the error details and submit them to FogBugz
  3. Have an error occur. ;)

I've published the code in a Gist for you a have a look. I include the function in every script I use.

 

Enum label lookup

In your datamodel you might have a Enum field such as this date-based dropdown:

public static $db = array(
    "Year"        => "Enum('2013, 2014, 2015')"
}

Internally, SilverStripe stores the index, so that when you retrieve the value in methods such as onBeforeWrite, instead of 2013 you will receive 1. Use the function below to retrieve the label of the Enum:

public function EnumLabel($field_name) {
    $enumValues = $this->dbObject($field_name)->enumValues();
    $label    = $enumValues[$this->$field_name];
    return $label;
}

// $year = $this->EnumLabel('Year');

 

LessThanOrEqual in SilverStripe 3.0

When adding a filter on a DataList sometimes you need to do a <= rather than a <. Unfortunately the LessThanOrEqual and GreatherThanOrEqual search filters do not exist in SilverStripe 3.0.x, they were added in 3.1.

Therefore we have to write our own where clause like the following example:

// Return all the sessions on or before the $date
$sessions = new DataList('AcademicSession');
$sessions = $sessions->where('"SessionStartDate" <= \'' . $date . '\'');

 

BugzScoutLogWriter 1.0

I've released another SilverStripe add-on called BugzScoutLogWriter that I have been using for several months on some of the sites at work.It supports SS 3.0 and 3.1.

BugzScoutLogWriter is a LogWriter that integrates logs with FogBugz, an integrated web-based project management system featuring bug/issue tracking made by FogCreek.

A LogWriter is attached to errors, warnings and notices that occur in a website due to programming errors or runtime errors and then sends / saves a log of this event. SilverStripe comes with built-in functionality to e-mail or save the logs to a file, however if you use a third party bug reporting system then it's nice to have all the issues collected there instead.

I've used FogBugz for years now and one of the nice features is that multiple occurrences of the same issue get collected in the same ticket. This keeps the whole process manageable. Say, in the event that a mistake that affects all pages on a website, FogBugz collects the first 50 occurrences of that error and lets you close the ticket with one click. This is an improvement to a flood of email.

Anyways let me know if you find it useful and feel free to raise issues.

 

How to provide and manage your own permissions

At some point on your journey through the jungle that is SilverStripe, you will want to create permissions and assign users to them. You might have created a Page Category model admin to categorise your pages, and setup the relations between pages and their category. By default when you create a category as an admin they will not be visible to any content authors and any content authors that can access the model admin can't create any new items.

The solution to this dilemma is to create a new permission (for example PROJECT_CategoryAdmin) and then let people with that permission mange the category items. This is how to go about it:

Create the permission

You will need to tell SilverStripe you are implementing permission by changing the class declaration as follows (changes in bold):

class Category extends DataObject implements PermissionProvider

To create the new permission you will have to write a providePermissions() method for the Category class:

      public function providePermissions() {
        return array(
            "PROJECT_CategoryAdmin" => array(
                'name' => 'Administer categories',
                'category' => 'PROJECT',
                'help' => 'Manage categories.'
            )
        );
    }

Finally, implement the permission by declaring the canCreate, canDelete, canEdit and canView methods to your liking:

    public function canCreate($member = null) {
        return Permission::check('PROJECT_CategoryAdmin');
    }

    public function canDelete($member = null) {
        return Permission::check('PROJECT_CategoryAdmin');
    }

    public function canEdit($member = null) {
        return Permission::check('PROJECT_CategoryAdmin');
    }

    public function canView($member = null) {
        return Permission::check('PROJECT_CategoryAdmin') ;
    }

Don't forget to create a Role and/or assign the permission to the right Group(s), to make sure the right users can manage your categories.

 

SilverStripe relation records management - or why do I have so many database records?

You have a bunch of DataObjects that has_many RelatedItems. You might have the following seperate situations:

  1. Get the Dataobject->RelatedItems() and remove() one RelatedItem. What happens to that RelatedItem?
  2. Delete() a DataObject. What happens to the RelatedItems for that DataObject?

Regarding 1: (in SilverStripe 3.0.x) - the DataObjectID for that RelatedItem is set to 0.

Regarding 2: Nothing, their DataObjectID will point to a non-existing record.

Wrong Expectations

In both cases I expected the objects to be deleted, but SilverStripe is going for safety first and keeps the records around just in case.

This means that you might need to write maintenance code if you don’t expect this happening.

Things to keep in mind

If you are writing an sync task and want to make sure RelatedItems are fresh, do not delete / remove RelatedItems before creating new ones. You will be creating thousands of records over time.

Instead, get the list of IDs, and unset the IDs that you find. Then remove any IDs left in the list as they weren’t in the source.

 

DisplayAnything3

DisplayAnything3 is a file and image gallery module for SilverStripe 3.0 with a big list of features. I'm looking forward to trying the module on a future project.

 

SilverStripe Gists

I've released the following data extensions (might pack them up as modules):

  • HiddenFields DataExtension: Takes form fields specified through $hidden_fields and hides them from edit form. View code
  • Description DataExtension: Specify a $db_descriptions array to DataObjects to attach formfield descriptions. View code

 

OptimisticLocking SilverStripe Module Release

Some of you might be interested in my first ss module: silverstripe-optimisticlocking

This is a very simple module that prevents your site users from losing data. It works by by blocking the save process if the record changed since it was retrieved, preventing accidental overwrites. (user1 starts editing, user 2 starts editing, user1 saves, now user2 can't overwrite user1's changes). By default, Silverstripe lets you lose data by overwriting the record on save.

You might know that Pages benefit from versioning (so you can restore to a previous version), however by default DataObjects don't have versioning enabled so this module will come in handy then (AFAIK it's not trivial to enable either).

If feedback is good, I will try to add it to the SilverStripe modules list.