All pages
Powered by GitBook
1 of 4

Developing for the CMS

The Elements CMS is a powerful content management system designed for RapidWeaver elements, providing a flexible and efficient way to manage content through markdown files with YAML front matter.

Table of Contents

  • Getting Started

  • Core Concepts

  • Working with Collections

  • Working with Items

  • Search Functionality

  • Related Items

  • RSS and Sitemap Generation

Getting Started

To initialize the CMS in your PHP code:

require_once 'path/to/cms.php';

// Initialize CMS with base path and options
$cms = cms('/path/to/content', [
    'detailPageUrl' => 'https://example.com/posts',
    'prettyUrls' => true
]);

Core Concepts

Collections

Collections are groups of content items stored in markdown files. Each collection is stored in a directory, with each item represented by a markdown file.

Items

Items are individual content pieces stored as markdown files with YAML front matter. The filename format can be either:

  • YYYY-MM-DD-slug.md (for dated content)

  • slug.md (for undated content)

Example item structure:

---
title: My Post Title
date: 2024-03-20
author: John Doe
tags: [news, technology]
categories: [blog]
featured: true
status: published
image:
    type: remote
    src: https://example.com/image.jpg
    alt: Image description
    width: 800
    height: 600
---

Content goes here...

Working with Collections

Basic Collection Operations

// Get a collection
$collection = $cms->collection('blog');

// Filter collection
$filtered = $collection->filter([
    'status' => 'published',
    'featured' => true
]);

// Order collection
$ordered = $collection->orderBy('date', 'desc');

// Paginate results
$paginated = $collection->paginate(1, 10);

Advanced Filtering

// Date-based filtering
$collection->whereDate('date', '>=', '2024-01-01');

// Custom filtering
$collection->filterWith(function($item) {
    return $item->featured() && $item->status() === 'published';
});

Working with Items

Loading and Accessing Items

// Load a specific item
$item = $cms->item('blog/my-post');

// Access item properties
$title = $item->title();
$date = $item->date('F j, Y');
$body = $item->body();
$excerpt = $item->excerpt(30);
$image = $item->image();
$url = $item->url();

// Access custom metadata
$customField = $item->meta('custom_field');

Item Relationships

// Load item with relationships
$item = $cms->item('blog/my-post')
    ->with('author', 'categories')
    ->withOne('featured_image')
    ->loadRelations();

// Access relationships
$author = $item->author;
$categories = $item->categories;
$featuredImage = $item->featured_image;

Search Functionality

The CMS includes a powerful search system that can be used in two ways:

PHP Search

// Search within a collection
$results = $collection->search('search term');

// The search results are scored based on where matches are found:
// - Title matches: 10 points
// - Excerpt matches: 5 points
// - Body matches: 1 point
// - Tag matches: 3 points per matching tag
// Results are automatically sorted by score in descending order

AJAX Search Endpoint

The CMS provides a search endpoint at search.php that accepts the following parameters:

  • q: Search query

  • collectionPath: Path to the collection

  • detailPageUrl: URL for detail pages

  • prettyUrls: Whether to use pretty URLs

  • basePath: Base path for content

  • template: HTML template for rendering results, can include Twig syntax

Example AJAX call:

// Alpine snippet
this.template = this.$el.querySelector(
    '[data-template="cmsCollectionSearchItemsTemplate"]'
).innerHTML;

const params = new URLSearchParams({
    q: this.query,
    collectionPath: "{{collectionDir.href}}",
    detailPageUrl: "{{detailPage.href}}",
    prettyUrls: "{{prettyUrls}}",
    basePath: "<?= __DIR__ ?>",
    template: this.template,
});

const res = await fetch(`{{cmsPath}}/search.php?${params}`, {
    method: "GET",
    headers: {
        "Content-Type": "application/json",
    },
});

The search system automatically maintains an index file (search-index.json) in the collection directory for improved performance. The index is automatically rebuilt when content changes are detected.

Related Items

The CMS provides a fluent interface for finding related items:

$related = $item->related()
    ->byTags()
    ->limit(5)
    ->excludeSelf()
    ->get();

// Or find by multiple criteria
$related = $item->related()
    ->by(['tags', 'author', 'categories'])
    ->in('blog')
    ->limit(3)
    ->get();

RSS and Sitemap Generation

RSS Feed

$rss = $collection->toRss(
    'My Blog',
    'Latest posts from my blog',
    'https://example.com/blog'
);

XML Sitemap

$sitemap = $collection->toSitemap(
    'https://example.com',
    'weekly',
    0.8
);

Best Practices

  1. File Organization

    • Keep collections in separate directories

    • Use consistent naming conventions for files

    • Include all necessary metadata in front matter

  2. Performance

    • Use caching when appropriate

    • Implement pagination for large collections

    • Optimize search queries

  3. Content Structure

    • Use consistent front matter fields

    • Include required metadata (title, date, status)

    • Properly format markdown content

  4. Security

    • Validate user input

    • Sanitize output

    • Use proper file permissions

Dependencies

The CMS requires the following PHP packages:

  • Symfony YAML

  • CommonMark

  • Illuminate Collections

  • Twig (for template rendering)

Error Handling

The CMS includes built-in error handling for common scenarios:

  • Invalid file paths

  • Missing required metadata

  • Malformed YAML front matter

  • Search index issues

Support

For issues, feature requests, or contributions, please refer to the project's issue tracker or documentation repository.

ElementsCMS.php

The ElementsCMS class is a PHP-based content management system that provides functionality for managing CMS collections and items. It serves as the main entry point for interacting with content stored

Overview

The ElementsCMS class manages the base path for content storage and provides methods to create collections, load items, and manage configuration options.

Constructor

__construct(string $basePath, array $options = [])

Creates a new instance of ElementsCMS.Parameters:

  • $basePath (string): The base path for the CMS content storage

  • $options (array, optional): Additional configuration options for the CMS

$cms = new ElementsCMS('/path/to/content', ['debug' => true]);

Static Methods

make(string $basePath, array $options = []): ElementsCMS

Static factory method that creates a new instance of ElementsCMS.Parameters:

  • $basePath (string): The base path for the CMS content storage

  • $options (array, optional): Additional configuration options for the CMS

Returns: ElementsCMS instance

$cms = ElementsCMS::make('/path/to/cms_data');

Configuration Methods

basePath(): string

Returns: The base path as a string

$path = $cms->basePath(); // Returns '/path/to/content'

options(): array

Returns: Array of all options

$allOptions = $cms->options();

option(string $key, $default = null): mixed

Returns: The option value or default value

Parameters:

  • $key (string): The option key to retrieve

  • $default (mixed, optional): Default value returned if the option is not set

$debug = $cms->option('debug', false);
$theme = $cms->option('theme', 'default');

setOption(string $key, $value): void

Sets an option value.

  • $key (string): The option key to set

  • $value (mixed): The value to set

$cms->setOption('debug', true);
$cms->setOption('cache_enabled', false);

Content Management Methods

collection(string $path, array $options = []): ElementsCMSCollection

Creates a new collection instance.Parameters:

  • $path (string): The path for the collection (relative to base path)

  • $options (array, optional): Additional options for the collection

Returns: ElementsCMSCollection instance

$articles = $cms->collection('articles', ['sort' => 'date']);
$projects = $cms->collection('projects');

item(string $collectionPath, string $slug): ?ElementsCMSItem

Loads a specific item from a collection.Parameters:

  • $collectionPath (string): The path of the collection

  • $slug (string): The slug/filename of the item (without .md extension)

Returns: ElementsCMSItem instance or null if not found

$blogPost = $cms->item('blog', 'my-first-post');
$aboutPage = $cms->item('pages', 'about');

Usage Examples

Basic Setup

<?php
require_once '/path/to/ElementsCMS.php';

$cms = ElementsCMS::make(
    '/var/www/cms_data',
    ['debug' => true, 'cache_ttl' => 3600]
);

Working with Collections

// Create a blog collection
$blog = $cms->collection('blog', ['sort' => 'date_desc']);

// Create a pages collection
$pages = $cms->collection('pages');

Loading Individual Items

// Load a specific blog post
$post = $cms->item('blog/introduction-to-cms');

// Load a page
$homepage = $cms->item('pages/home');

Managing Configuration

// Get configuration
$debugMode = $cms->option('debug', false);
$cacheEnabled = $cms->option('cache_enabled', true);

// Set configuration
$cms->setOption('theme', 'custom');
$cms->setOption('max_items_per_page', 10);

Dependencies

This class requires the following files:

  • ElementsCMSCollection.php

  • ElementsCMSItem.php

Make sure these files are available in the same directory as the ElementsCMS class.

File Structure

The CMS expects content to be organized in the following structure:

  • cms-base-path/

    • collection-name/

      • item-slug.md

      • another-item.md

    • another-collection/

      • item1.md

      • item2.md

Items must be in Markdown files (.md extension) within collection directories.

ElementsCMSCollection

A collection class for managing CMS items, providing methods for filtering, ordering, pagination, and searching.

Constructor

__construct(ElementsCMS $cms, string $path, array $options = [])

Creates a new collection instance.

  • $cms (ElementsCMS): The CMS instance.

  • $path (string): Path to the collection (folder).

  • $options (array): Additional options for the collection.


Instance Methods

with(string ...$relations): self

Add relations to be eager-loaded for all items in the collection.

  • $relations (string ...): One or more relation names.

  • Returns: $this (for chaining)

filter(array $criteria = []): self

Filter items in the collection by key/value pairs.

  • $criteria (array): Associative array of criteria (e.g., ['status' => 'published'])

  • Returns: $this (for chaining)

filterWith(callable $callback): self

Filter items in the collection using a custom callback.

  • $callback (callable): Function that receives an item and returns true to keep, false to exclude.

  • Returns: $this (for chaining)

orderBy(string $field, string $direction = 'desc'): self

Order the collection by a specified field.

  • $field (string): Field name to order by.

  • $direction (string): 'asc' or 'desc' (default: 'desc')

  • Returns: $this (for chaining)

whereDate(string $field, string $operator, string $date): self

Filter items by date field using a comparison operator.

  • $field (string): Date field to compare (e.g., 'published_date')

  • $operator (string): Comparison operator (e.g., '>=', '==', '<')

  • $date (string): Date value for comparison.

  • Returns: $this (for chaining)

paginate(int $page = 1, int $perPage = 10): array

Paginate the collection.

  • $page (int): Page number (default: 1)

  • $perPage (int): Items per page (default: 10)

  • Returns: array — Paginated results, typically including items, total, page, per_page, etc.

getCollection(): LaravelCollection

Returns the underlying Laravel collection of items.

  • Returns: Illuminate\Support\Collection of ElementsCMSItem objects.

findBySlug(string $slug): ?ElementsCMSItem

Find an item in the collection by its slug.

  • $slug (string): The slug to search for.

  • Returns: ElementsCMSItem|null

search(string $query): array

Search the collection items by query string.

  • $query (string): The search term.

  • Returns: array — Array of matching ElementsCMSItem objects.


Usage Example

$collection = new ElementsCMSCollection($cms, 'posts', [
    'expectDates' => true
]);

// Filter, order, and paginate items
$results = $collection
    ->filter(['status' => 'published'])
    ->orderBy('published_date', 'desc')
    ->paginate(1, 10);

// Find a specific item by slug
$item = $collection->findBySlug('hello-world');

// Search items
$matches = $collection->search('static site generator');

ElementsCMSItem.php

Represents a single CMS item loaded from a Markdown file with front matter. Provides structured access to metadata, raw and rendered content, file paths, and relationships to other items.

Constructor

__construct(ElementsCMS $cms, array $data = [])

Creates a new CMS item.

  • $cms (ElementsCMS): The CMS instance.

  • $data (array): The data for the CMS item.


Static Methods

static load(ElementsCMS $cms, string $filepath): ?self

Load a CMS item from a file.

  • $cms (ElementsCMS): The CMS instance.

  • $filepath (string): Path to the file.

  • Returns: ElementsCMSItem|null – Loaded item or null if not found.


Instance Methods

setOptions(array $options): self

Sets runtime options for the item.

  • $options (array): Option key/value pairs.

  • Returns: $this for method chaining.

getOption(string $key, $default = null)

Gets an option value by key.

  • $key (string): Option name.

  • $default (mixed): Default value if not found.

  • Returns: Mixed option value.

slug(): string

Returns the item’s slug (URL-friendly identifier).

title(): string

Returns the item’s title.

date(string $format = 'F j, Y'): string

Returns the item's date in the given format.

  • $format (string): Date format (default 'F j, Y').

datePublished(string $format = 'F j, Y'): string

Returns the item's published date.

dateModified(string $format = 'F j, Y'): string

Returns the item's last modified date.

featured(): bool

Checks if the item is marked as featured.

status(): string

Returns the item's status (e.g., published/draft).

body(): string

Returns the rendered HTML body content.

rawBody(): string

Returns the raw markdown body content.

image(): ?string

Returns the item's image URL, if available.

excerpt(int $words = 30): string

Returns an excerpt of the body, limited to the specified word count.

meta(string $key, $default = null): mixed

Fetches a value from the item's metadata/front-matter.

  • $key (string): Meta key.

  • $default (mixed): Default if key is missing.

attach(string $key, $value): self

Attach related data to the item (e.g., relations, computed properties).

get(string $key, $default = null): mixed

Returns any value from the item data or metadata.

__call($method, $arguments)

Allows dynamic method access to metadata fields.

file(): string

Returns the full path to the file.

fileName(): string

Returns the base filename (without extension).

url(): string

Returns the item’s URL.

lastModified(string $format = 'F j, Y'): string

Returns the file's last modified date.

toArray(): array

Returns all item data as an associative array.

with(string ...$relations): self

Declare relations (one-to-one or one-to-many) to eager-load.

withOne(string ...$relations): self

Declare one-to-one relations to eager-load.

withMany(string ...$relations): self

Declare one-to-many relations to eager-load.

loadRelations(): self

Loads all defined relations for the item.


Usage Example

$cms = new ElementsCMS(/* ... */);
$item = ElementsCMSItem::load($cms, 'posts/hello-world');

if ($item) {
    echo $item->title();           // Item title
    echo $item->body();            // Rendered body
    echo $item->datePublished();   // Published date
    $item->with('author', 'categories')->loadRelations();
}