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

Add "events" for performing user-defined actions before or after a build #189

merged 16 commits into from Mar 9, 2018


Copy link

@damiani damiani commented Mar 5, 2018

This PR allows users to hook into "events" in order to run custom code before and after a build is processed. It combines ideas from issues #135 and #175, and PRs #136 and #165. It can also serve as the basis for addressing #120.

There are three events a user can listen to:

  • beforeBuild is fired before any source files have been processed. This gives the user an opportunity to programmatically modify config variables, fetch data from external sources, or modify files in the source folder.

  • afterCollections is fired after any collections have been processed, but before any output files are built. This gives the user access to the parsed contents of collection items.

  • afterBuild is fired after the build is complete, and all output files have been written to the build directory. This allows the user to obtain a list of the output file paths (to use, for example, when creating a sitemap.xml file), programmatically create output files, or take care of any other post-processing tasks.

Registering event listeners (as closures)

To add an event listener, head over to bootstrap.php. There, you can access the event bus with the $events variable, adding listeners by calling the name of the event:


$events->beforeBuild(function ($jigsaw) {
   // your code here

$events->afterCollections(function ($jigsaw) {
   // your code here

$events->afterBuild(function ($jigsaw) {
   // your code here

At its simplest, you can define your event listeners as closures that accept an instance of Jigsaw. The Jigsaw instance contains a number of helper methods (see below) to allow you to access information about the site and interact with files and config settings.

For example, the following listener will fetch the current weather from an external API, and add it as a variable to config.php, where it can be referenced in your templates:


$events->beforeBuild(function ($jigsaw) {
    $url = "" . http_build_query([
        'q' => $jigsaw->getConfig('city'),
        'appid' => $jigsaw->getConfig('openweathermap_api_key'),
        'units' => 'imperial',

    $jigsaw->setConfig('current_weather', json_decode(file_get_contents($url))->main);

Registering event listeners (as classes)

For more complex event listeners, you can specify the name of a class, or an array of class names, instead of a closure. These classes can either live in bootstrap.php or in a separate directory. Listener classes should countain a handle() method with accepts an instance of Jigsaw:



// or

$events->afterBuild([GenerateSitemap::class, SendNotification::class]);


<?php namespace App\Listeners;

use TightenCo\Jigsaw\Jigsaw;
use samdark\sitemap\Sitemap;

class GenerateSitemap
    public function handle(Jigsaw $jigsaw)
        $baseUrl = $jigsaw->getConfig('baseUrl');
        $sitemap = new Sitemap($jigsaw->getDestinationPath() . '/sitemap.xml');

        collect($jigsaw->getOutputPaths())->each(function ($path) use ($baseUrl, $sitemap) {
            if (! $this->isAsset($path)) {
                $sitemap->addItem($baseUrl . $path, time(), Sitemap::DAILY);


    public function isAsset($path)
        return starts_with($path, '/assets');

If there are multiple listeners defined for a single event, they will be fired in the order in which they were defined.

To call a listener class that lives in a separate directory, the class namespace should be added to a composer.json file:


    "autoload": {
        "psr-4": {
            "App\\Listeners\\": "listeners"

Helper methods in $jigsaw

The instance of Jigsaw available to each event listener includes the following helper methods:

Method Description
getEnvironment() Returns the current environment, e.g. local or production
getCollections() in beforeBuild, returns an array of collection names; in afterCollections and afterBuild, returns a collection of collection items, keyed by collection name.
getCollection($collection) (afterCollections and afterBuild only) Returns the items in a particular collection, keyed by their source filenames. Each item contains the variables defined for the collection item, as well as access to all collection item methods like getContent().
getConfig() Returns the settings array from config.php
getConfig($key) Returns a specific setting from config.php
setConfig($key, $value) Adds or modifies a setting in config.php
getSourcePath() Returns the absolute path to the source directory
setSourcePath($path) Sets the path to the source directory
getDestinationPath() Returns the absolute path to the build directory
setDestinationPath($path) Sets the path to the build directory
getOutputPaths() (afterBuild only) Returns an array of paths to the output files that were generated, relative to the build directory
readSourceFile($fileName) Returns the contents of a file in the source directory
writeSourceFile($fileName, $contents) Allows you to write a file to the source directory
readOutputFile($fileName) Returns the contents of a file in the build directory
writeOutputFile($fileName, $contents) Allows you to write a file to the build directory
# Conflicts:
#	jigsaw-core.php
#	src/DataLoader.php
#	src/Jigsaw.php
#	src/SiteBuilder.php
#	tests/CollectionItemTest.php
@damiani damiani merged commit 03c5d23 into master Mar 9, 2018
@damiani damiani deleted the kd-events branch Mar 18, 2018
@damiani damiani mentioned this pull request May 3, 2018
Copy link

@RohanSakhale RohanSakhale commented May 10, 2018

Is this event bus mechanism available in latest Jigsaw?
Can you also update documentation on public site.

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

Successfully merging this pull request may close these issues.

None yet

2 participants