Event Listeners

Jigsaw provides three events that you can hook into, in order to run custom code before and after your build is processed.

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

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

  • An afterBuild event is fired after the build is complete, and all output files have been written to the build directory. This allows you 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:

bootstrap.php

1$events->beforeBuild(function ($jigsaw) {
2 // your code here
3});
4 
5$events->afterCollections(function ($jigsaw) {
6 // your code here
7});
8 
9$events->afterBuild(function ($jigsaw) {
10 // your code here
11});

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 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:

bootstrap.php

1$events->beforeBuild(function ($jigsaw) {
2 $url = "http://api.openweathermap.org/data/2.5/weather?" . http_build_query([
3 'q' => $jigsaw->getConfig('city'),
4 'appid' => $jigsaw->getConfig('openweathermap_api_key'),
5 'units' => 'imperial',
6 ]);
7 
8 $jigsaw->setConfig('current_weather', json_decode(file_get_contents($url))->main);
9});

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 directly in bootstrap.php or in a separate directory. Listener classes should countain a handle() method with accepts an instance of Jigsaw:

bootstrap.php

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

listeners/GenerateSitemap.php

1<?php
2 
3namespace App\Listeners;
4 
5use TightenCo\Jigsaw\Jigsaw;
6use samdark\sitemap\Sitemap;
7 
8class GenerateSitemap
9{
10 public function handle(Jigsaw $jigsaw)
11 {
12 $baseUrl = $jigsaw->getConfig('baseUrl');
13 $sitemap = new Sitemap($jigsaw->getDestinationPath() . '/sitemap.xml');
14 
15 collect($jigsaw->getOutputPaths())->each(function ($path) use ($baseUrl, $sitemap) {
16 if (! $this->isAsset($path)) {
17 $sitemap->addItem($baseUrl . $path, time(), Sitemap::DAILY);
18 }
19 });
20 
21 $sitemap->write();
22 }
23 
24 public function isAsset($path)
25 {
26 return starts_with($path, '/assets');
27 }
28}

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:

composer.json

1{
2 "autoload": {
3 "psr-4": {
4 "App\\Listeners\\": "listeners"
5 }
6 }
7}

Helper methods in $jigsaw

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


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.
Dot notation (e.g. getConfig('collections.posts.items') can be used to get nested items.


setConfig($key, $value)

Adds or modifies a setting in config.php.
Dot notation can be used to set nested items.


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


getPages() (afterBuild only)

Returns a collection of all output files that were generated. For each item, the key contains the path of the output file relative to the build directory (e.g. /posts/my-first-post), while the value contains the contents of the $page variable for the source file. This exposes the page metadata functions such as getPath() and getModifiedTime() for each page, as well as any variables defined in the page's YAML header.


getOutputPaths() (afterBuild only)

Returns a collection 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