Helper plugin to install SilverStripe recipes

Overview

SilverStripe recipe-plugin

Introduction

This plugin enhances composer and allows for the installation of "silverstripe-recipe" packages. These recipes allow for the following features:

  • The ability to provide project resource files. These are copied to the appropriate project root location on install, and can be safely modified by the developer. On subsequent updates to a later recipe, composer will inform the user if a project file has been updated, and will ensure new files are copied as they are introduced to the recipe.
  • Recipes are composable, so resources or dependencies that are required by multiple recipes can include one another, rather than having to duplicate content.
  • Recipes also can be used as a base composer project.
  • A require-recipe command to inline a recipe into the root composer.json, allowing the developer to customise the recipe dependencies without mandating the inclusion of all requirements directly.
  • An update-recipe command to upgrade to a newer version of a recipe.

Example output

example-output

Creating a new project

Recipes can be introduced to any existing project (even if not created on a silverstripe base project)

$ composer init
$ composer require silverstripe/recipe-cms ^1.0@dev

Alternatively you can create a new project based on an existing recipe

$ composer create-project silverstripe/recipe-cms ./myssproject ^1.0@dev

Inlining recipes

You can "inline" either a previously installed recipe, or a new one that you would like to include dependencies for in your main project. By inlining a recipe, you promote its requirements, as well as its project files, up into your main project, and remove the recipe itself from your dependencies.

This can be done with either update-recipe, which will update a recipe, or require-recipe which will install a new recipe.

Note that if you wish to run this command you must first install either a recipe via normal composer commands, or install the recipe plugin:

$ composer init
$ composer require silverstripe/recipe-plugin ^0.1
$ composer require-recipe silverstripe/recipe-cms ^1.0@dev

or

$ composer init
$ composer require silverstripe/recipe-cms ^1.0@dev
$ composer update-recipe silverstripe/recipe-cms

Removing recipe dependencies or files

Any project file installed via a recipe, or any module installed by inlining a recipe, can be easily removed. Subsequent updates to this recipe will not re-install any of those files or dependencies.

In order to ensure this, a record of all inlined modules, and all installed files are stored in composer.json as below.

{
    "extra": {
        "project-files-installed": [
            "mysite/code/Page.php",
            "mysite/code/PageController.php"
        ],
        "project-dependencies-installed": {
            "silverstripe/admin": "1.0.x-dev",
            "silverstripe/asset-admin": "1.0.x-dev",
            "silverstripe/campaign-admin": "1.0.x-dev"
        }
    }
}

To remove a file, simply delete it from the folder your project is installed in, but don't modify project-files-installed (as this is how composer knows what not to re-install).

Likewise to remove a module, use composer remove <module> and it will be removed. As above, don't modify project-dependencies-instaleld, otherwise that module will be re-installed on subsequent composer update-recipe.

Un-doing a deleted project file / dependency

If you have deleted a module or file and want to re-install it you should remove the appropriate entry from either 'project-files-installed' or 'project-dependencies-installed' and then run composer update-recipe <recipe> again.

The file or module will be re-installed.

Removing recipes

As installation of a recipe inlines all dependencies and passes ownership to the root project, there is no automatic removal process. To remove a recipe, you should manually remove any required module that is no longer desired via composer remove <module>.

The provide reference to the recipe can also be safely removed, although it has no practical result other than to disable future calls to update-recipe on this recipe.

Installing or upgrading recipes without inlining them

If desired, the optional inline behaviour of recipes can be omitted. Simply use the composer commands require and update in place of require-recipe and update-recipe respectively. This will not disable the project files feature, but will not inline the recipe directly, keeping your root composer.json from getting cluttered.

If you have already inlined a recipe, it will be necessary to manually remove any undesired inlined requirements manually, and the recipe will need to be included with require subsequently.

Note that using this method it's not necessary to include the silverstripe/recipe-plugin in the root project for this to work.

Recipe composer.json schema

Recipe types should follow the following rules:

  • No mandatory resources, other than project files.
  • Recipes must not rely on autoload as this are discarded on inline. Likewise any *-dev or other root-only options should not be used, as these are ignored outside of the root project. The exception to this is when these values are useful as a base project only.
  • The type must be silverstripe-recipe
  • The require must have silverstripe/recipe-plugin as a dependency.
  • extra.project-files must be declared as a list of wildcard patterns, matching the files in the recipe root as they should be copied to the root project. The relative paths of these resources are equivalent.
  • extra.public-files must be declared for any files which should be copied to the public web folder. If the project in question doesn't have any public folder, these will be copied to root instead. Note that all public files must be committed to the recipe public folder.

An example recipe:

{
    "name": "silverstripe/example-recipe",
    "description": "Example silverstripe recipe",
    "type": "silverstripe-recipe",
    "require": {
        "silverstripe/recipe-plugin": "^0.1",
        "silverstripe/recipe-cms": "^1.0",
        "silverstripe/blog": "^3.0@dev",
        "silverstripe/lumberjack": "^2.1@dev",
    },
    "extra": {
        "project-files": [
            "mysite/_config/*.yml",
            "mysite/code/MyBlogPage.php"
            "client/src/*"
        ],
        "public-files": [
            "client/dist/*"
        ]
    },
    "prefer-stable": true,
    "minimum-stability": "dev"
}

The files within this recipe would be organised in the structure:

client/
  src/
    blog.scss
mysite/
 _config/
    settings.yml
  code/
    MyBlogPage.php
public/
  client/
    dist/
      blog.css
composer.json
Comments
  • ENHANCEMENT: Don't re-install files/modules the developer intentionally removed or moved

    ENHANCEMENT: Don't re-install files/modules the developer intentionally removed or moved

    As a developer, I want to use a recipe with features removed, to gain flexibility

    • [x] I can inline a recipe, transferring its requirements into my project
    • [x] I can remove a module provided by the recipe, and it won't be added during a recipe-upgrade
    • [x] I can remove a file provided by the recipe, and it won't be added during a recipe-upgrade

    PRs

    • [x] https://github.com/silverstripe/recipe-plugin/pull/3

    Potential implementations

    .gitignore

    If a root project has a file pattern in .gitignore or .gitattributes then the plugin should probably not try to copy project files to the root. This can be used to suppress undesirable project resources. It's not clear how this would supress a module

    .recipe.json

    Whenever a project file is installed, the plugin registers this somewhere that can be later checked. On subsequent installs, these files won't be re-installed if they exist in this registered location. E.g. .recipe.json file in root.

    It could also be JSON content within composer.json

    Reference to previously installed recipe

    Instead of including the full data of the previously installed recipe, composer.json could just include the name & version (w/ SHA for dev branches) of the recipe, and look up the details during a recipe-upgrade command.

    In edge-cases such as tags being edited, this could lead to errors, but these cases are rare and the impact would likely be to reinstall the previously-removed module, which is relatively benign and easily recovered from.

    The benefit would be less junk bloating the repository.

    type/enhancement affects/v4 impact/medium 
    opened by tractorcow 24
  • NEW Allow files to have a .tmpl extension which is stripped

    NEW Allow files to have a .tmpl extension which is stripped

    Allows a fix for https://github.com/silverstripe/recipe-cms/issues/9

    --

    Added:

    • Tests, travis integration, test namespaces and autoloading
    • Added APIs to better facilitate mocking (such as file_exists, file_get_contents, copy, etc)
    • Support for recipe files to end in .tmpl so that they don't get picked up by IDEs as first class classes
    opened by dhensby 11
  • Refs to mysite dir maintained in composer.json

    Refs to mysite dir maintained in composer.json

    Overview

    I'm having trouble understanding how both the "public" and "mysite" dirs are created when using "type: "silverstripe-recipe" in my project's "composer.json". In lieu of the resolution to silverstripe/silverstripe-framework#7946 the recipe will create a "mysite" dir for me, even if I already have an "app" dir present. The only way to prevent this is to ensure I maintain the relevant entries in composer's "extra" block ala:

       "extra": {
            "project-files-installed": [
                "mysite/.htaccess",
                "mysite/_config.php",
                "mysite/_config/mysite.yml",
                "mysite/code/Page.php",
                "mysite/code/PageController.php"
            ],
    

    ...which if I'm not ever intending on using "mysite" - ever - seems a bit wasteful, just to prevent the recipe from creating the dir. Perhaps I'm missing something, otherwise at worst I'd call this a bug and at best, a wee bit of technical debt to have to maintain.

    Acceptance Criteria

    • As a dev with an app folder upgrading a 3.x install, I don't want to deal with recipe internals in order to stop it from copying files into the wrong place on any composer update call
    • If I have an app folder, any default files located in mysite of the recipe-core will be placed in the same directory structure in app

    Notes

    • We'll be using app going forward (most likely in 4.2) anyway
    • The upgrader notes if there's no app folder, separate issue
    • Assumption: Does not rely on shifting composer metadata into a recipe.lock file
    type/enhancement affects/v4 impact/high type/api-break complexity/medium rfc/draft 
    opened by phptek 10
  • Composer 2 introduces non-BC changes

    Composer 2 introduces non-BC changes

    Trying to install using Composer 2 fails as the plugin version needs to be updated to 2.0 - you can see the requirements here: https://github.com/composer/composer/blob/master/UPGRADE-2.0.md#user-content-for-integrators-and-plugin-authors

    Output from user on Slack:

    :~/httpdocs$ composer update
    Loading composer repositories with package information
    Updating dependencies
    Your requirements could not be resolved to an installable set of packages.
     Problem 1
      - silverstripe/recipe-plugin 0.1.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - silverstripe/recipe-plugin 0.2.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - silverstripe/recipe-plugin 1.0.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - silverstripe/recipe-plugin 1.1.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - silverstripe/recipe-plugin 1.2.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - silverstripe/recipe-plugin 1.3.0 requires composer-plugin-api ^1.1 -> found composer-plugin-api[2.0.0] but it does not match your constraint.
      - Root composer.json requires silverstripe/recipe-plugin @stable -> satisfiable by silverstripe/recipe-plugin[1.3.0, 1.2.0, 1.1.0, 1.0.0, 0.2.0, 0.1.0].
    You are using a snapshot build of Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report an issue to them to ask them to support Composer 2. To work around this you can run Composer with --ignore-platform-reqs, but this will also ignore your PHP version and may result in bigger problems down the line.
    

    Shouldn't be too difficult of a change but will need to be done before Composer 2 is widely adopted

    Pulls request

    • [x] https://github.com/silverstripe/recipe-plugin/pull/16
    • [x] https://github.com/silverstripe/vendor-plugin/pull/36
    type/bug affects/v4 impact/high 
    opened by andrewandante 5
  • MNT Use GitHub Actions CI

    MNT Use GitHub Actions CI

    Issue https://github.com/silverstripe/gha-ci/issues/11

    Workflow run https://github.com/creative-commoners/recipe-plugin/actions?query=branch%3Apulls%2F1.7%2Fmodule-standards

    opened by emteknetnz 4
  • Composer 2.3.2 crash on vendor-expose or any recipe-plugin commands (e.g. update-recipe)

    Composer 2.3.2 crash on vendor-expose or any recipe-plugin commands (e.g. update-recipe)

    Composer 2.3.2 was released yesterday. Ever since composer vendor-expose fails:

    > composer vendor-expose
    PHP Fatal error:  Declaration of Composer\Command\BaseCommand::getComposer(bool $required = true, ?bool $disablePlugins = NULL, ?bool $disableScripts = NULL) must be compatible with SilverStripe\RecipePlugin\RecipeCommandBehaviour::getComposer($required = true, $disablePlugins = NULL) in /home/tim/Sites/scratch-silverstripe/vendor/silverstripe/recipe-plugin/src/RequireRecipeCommand.php on line 73
    
    Fatal error: Declaration of Composer\Command\BaseCommand::getComposer(bool $required = true, ?bool $disablePlugins = NULL, ?bool $disableScripts = NULL) must be compatible with SilverStripe\RecipePlugin\RecipeCommandBehaviour::getComposer($required = true, $disablePlugins = NULL) in /home/tim/Sites/scratch-silverstripe/vendor/silverstripe/recipe-plugin/src/RequireRecipeCommand.php on line 73
    

    Downgrading to Composer 2.2.10 works. This is with vendor-plugin 1.5.2

    This is on a scratch SS site with a small composer.json:

    
    {
        "name": "silverstripe/installer",
        "type": "silverstripe-recipe",
        "description": "The SilverStripe Framework Installer",
        "require": {
            "php": "^7.3 || ^8.0",
            "silverstripe/recipe-plugin": "^1.2",
            "silverstripe/recipe-cms": "~4.10.0@stable",
            "silverstripe-themes/simple": "~3.2.0",
            "silverstripe/login-forms": "~4.6.0@stable"
        },
        "require-dev": {
            "phpunit/phpunit": "^9.5",
            "silverstripe/behat-extension": "^4.8"
        },
        "extra": {
            "resources-dir": "_resources",
            "project-files-installed": [
                "app/.htaccess",
                "app/_config.php",
                "app/_config/mimevalidator.yml",
                "app/_config/mysite.yml",
                "app/src/Page.php",
                "app/src/PageController.php"
            ],
            "public-files-installed": [
                ".htaccess",
                "index.php",
                "web.config"
            ]
        },
        "config": {
            "process-timeout": 600,
            "allow-plugins": {
                "composer/installers": true,
                "silverstripe/recipe-plugin": true,
                "silverstripe/vendor-plugin": true
            }
        },
        "prefer-stable": true,
        "minimum-stability": "dev"
    }
    
    
    type/bug impact/high complexity/medium 
    opened by tim-mediasuite 4
  • Install a package if 2 other packages are installed

    Install a package if 2 other packages are installed

    If you have installed both userforms and elemental, then you will likely want to install dnadesign/silverstripe-elemental-userforms. It would be nice to automated this in a recipe.

    Suggested syntax is a "extra.require-optional" config option:

    {
        "name": "silverstripe/recipe-content-blocks",
        "type": "silverstripe-recipe",
        "require": {
            "silverstripe/elemental-blocks": "1.0.x-dev"
        },
        "extra": {
            "require-optional": {
              "dnadesign/silverstripe-elemental-userforms:^1": {
                "if-installed": [ "silverstripe/userforms:*" ],
               }
            }
        }
    }
    

    A few notes:

    • the keys are package:constraint pairs, this would let you optionally install different versions based on different conditions
    • The if-installed checks are package:constraint pairs for different reasons
    • if-not-installed would be another option.
    • As well as package constraints you could use php & php-extension checks as composer currently does. This might be an add-on for later.
    • I'm not sure if there are other options that could be added.

    Implementation implications:

    • It would require that there's a couple of passes over the dependency resolver. This, btw, is one reason why composer have never added such functionality themselves.
    type/enhancement affects/v4 complexity/medium 
    opened by sminnee 4
  • Add an unpack command to allow ejection of code from recipes.

    Add an unpack command to allow ejection of code from recipes.

    Sometimes you need to remove the recipe configuration for more control over your dependency set.

    This is a pretty slimmed down version of what is available with Symfony - http://fabien.potencier.org/symfony4-unpack-the-packs.html

    I took most of the code directly from Flex, so have included a link to their LICENSE file in the readme.

    opened by stevie-mayhew 3
  • Placeholder for peer review

    Placeholder for peer review

    Please leave peer review comments on the module here.

    Link back to main issue: https://github.com/silverstripe/silverstripe-framework/issues/6860

    You can test using the following recipes:

    • tractorcow/recipe-core
    • tractorcow/recipe-cms

    Note that until we move this to silverstripe org, the plugin is tractorcow/recipe-plugin, although the docs are written with the final name in mind. :)

    opened by tractorcow 3
  • FIX Only write composer.json if there are changes

    FIX Only write composer.json if there are changes

    Caught this on a deployment to one of our platforms, even though no changes were made, the file was still read into memory and rewritten. Unfortunately, that triggered this issue: https://github.com/composer/composer/issues/9515 with an empty "scripts": {} key being rewritten to "scripts": []

    This doesn't totally fix it but it does prevent a few unnecessary writes and saves the day in that one use-case

    opened by andrewandante 2
  • FIX Always put public resources in a public/ dir

    FIX Always put public resources in a public/ dir

    The public/ directory is mandatory in CMS 5 (some of the functionality had already been explicitly deprecated in CMS 4 and so it has been removed in CMS 5) - but if the public/ dir didn't exist yet, this plugin was still putting files from extra.public-files in composer.json of recipes into the project root. This has been causing our behat tests to fail in CI for most modules.

    Note

    Any deprecations required in CMS 4 or updates to documentation will be done separately - the primary purpose of this PR is to get builds passing again.

    Related RFC

    https://github.com/silverstripe/silverstripe-framework/issues/8168

    Parent Issue

    • https://github.com/silverstripeltd/product-issues/issues/642
    opened by GuySartorelli 0
  • Empty scripts tag will be re-written to invalid JSON using Composer 1

    Empty scripts tag will be re-written to invalid JSON using Composer 1

    See: #21

    This is a parent issue to warn against including an empty object tag in your composer.json - because if it gets overwritten it will be written back with an empty array instead, causing composer validate and other checks like that to fail.

    Covered here: https://github.com/composer/composer/issues/9515 by composer themselves.

    type/bug impact/medium 
    opened by andrewandante 0
  • Cannot control priority of project files between recipes

    Cannot control priority of project files between recipes

    I have a situation where I have two recipe dependencies which both have the same project file:

    • silverstripe/recipe-core: app/_config.php
    • cwp/cwp-recipe-core: app/_config.php

    Because app/_config.php from silverstripe/recipe-core is run before pretty much anything else (as a close-to-root dependency), it takes the project file from there and copies it into my project. Subsequent recipes such as cwp/cwp-recipe-core cannot copy their own file after this, because they get ignore as "existing or modified in project."

    The problem in this example is really that the file contains password complexity requirements, and because they are then copied into user code they will take priority over everything else. CWP needs to increase the minimum requirements but it can't do so at the moment.

    type/enhancement affects/v4 impact/medium complexity/medium 
    opened by robbieaverill 1
  • composer vendor-expose overwrite folder with broken synlink

    composer vendor-expose overwrite folder with broken synlink

    Let's say you create a file under app/css/bob.css and update your project composer.json file like this:

    {
    "extra": {
            "expose": [
                "app/css"
            ]
        }
    }
    

    If you run a composer vendor-expose, bob.css and the css will be deleted and a new app/css symlink will be created. That symlink will point to a broken ../../../app/css location.

    type/bug affects/v4 impact/high complexity/medium 
    opened by maxime-rainville 4
  • Minor: better indentation of recipe install command output

    Minor: better indentation of recipe install command output

    image

    Super minor, but it might look a bit nicer if the output of the recipe plugin/vendor plugins were indented further than they are to form more of a tree

    type/enhancement impact/low complexity/low 
    opened by robbieaverill 1
  • composer.json and composer.lock out of sync after installing recipe

    composer.json and composer.lock out of sync after installing recipe

    If you install a recipe, your composer set up will be invalid.

    Step to reproduce

    1. Create a new directory.
    2. Save the sample composer.json in your new directory.
    3. Require recipe-cms: composer require silverstripe/recipe-cms
    4. The command will complete successfully.
    5. Run a composer validate.
    6. The command will complain that The lock file is not up to date with the latest changes in composer.json, it is recommended that you run composer update.

    Expected results: A successful composer require on a valid composer.json should leave you in a valid state.

    Sample composer.json file

    {
        "name": "maxime/composer-test",
        "description": "foobar",
        "type": "project",
        "license": "mit",
        "authors": [
            {
                "name": "Maxime Rainville",
                "email": "[email protected]"
            }
        ],
        "minimum-stability": "dev",
        "require": {}
    }
    

    Underlying cause of problem

    composer.lock contains an hash calculated from a few values contained composer.json. The problem is that installing recipes will add new properties to the extra object in composer.json after the composer.lock hash has been generated.

    There's an easy workaround ... which is to just run a composer update ... but it's kind of an annoyance for the silverstripe upgrader.

    type/enhancement affects/v4 impact/low 
    opened by maxime-rainville 0
Releases(1.7.0)
Owner
Silverstripe CMS
Silverstripe CMS is the intuitive content management system and flexible framework loved by editors and developers alike.
Silverstripe CMS
Silverstripe-debugbar/ - SilverStripe DebugBar module

SilverStripe DebugBar module Requirements SilverStripe ^4.0 maximebf/php-debugbar jdorn/sql-formatter Installation You can install the debug bar with

Thomas Portelange 52 Dec 21, 2022
Silverstripe-fulltextsearch - Adds external full text search engine support to SilverStripe

FullTextSearch module Adds support for fulltext search engines like Sphinx and Solr to SilverStripe CMS. Compatible with PHP 7.2 Important notes when

Silverstripe CMS 42 Dec 30, 2022
Silverstripe-searchable - Adds to the default Silverstripe search by adding a custom results controller and allowing properly adding custom data objects and custom fields for searching

SilverStripe Searchable Module UPDATE - Full Text Search This module now uses Full Text Support for MySQL/MariaDB databases in version 3.* Adds more c

ilateral 13 Apr 14, 2022
A SilverStripe module for conveniently injecting JSON-LD metadata into the header of each rendered page in SilverStripe

A SilverStripe module for conveniently injecting JSON-LD metadata into the header of each rendered page in Silver

null 4 Apr 20, 2022
Cookbook-magento - Collection of recipes to build app stack for the Magento deployments with Chef

Magento Cookbook Collection of recipes to build app stack for the Magento deployments with Chef Installation With Berkshelf echo "cookbook 'magento',

Yevhen Viktorov 37 Sep 26, 2020
Repository containing all the PHPStan rules from the book "Recipes for Decoupling"

PHPStan rules from the book "Recipes for Decoupling" by Matthias Noback In the book "Recipes for Decoupling" we discuss how to decouple from web and C

Matthias Noback 19 Sep 21, 2022
A wrapper around symplify/config-transformer used to update recipes and using easy coding standard for generating readable config files.

Symfony Recipes Yaml to PHP Converter This is a wrapper around the symplify/config-transformer used to convert Symfony core recipes which uses .yaml c

Alexander Schranz 3 Nov 24, 2022
A composer plugin, to install differenty types of composer packages in custom directories outside the default composer default installation path which is in the vendor folder.

composer-custom-directory-installer A composer plugin, to install differenty types of composer packages in custom directories outside the default comp

Mina Nabil Sami 136 Dec 30, 2022
SilverStripe Garbage Collection Module

SilverStripe Module for defining and processing Garbage Collection on SilverStripe Applications.

Brett Tasker 8 Aug 12, 2022
Phalcon 3.x BB Debugger Strong and easy install.

Phalcon BB Debugger Phalcon Version: 3.x BB Debugger Version: 1.0.3 Change Log See ChangeLog What is BB Debugger ? The bb debugger, written for the ph

İsmail 6 Oct 7, 2022
Easily install PHP extension in Docker containers

Easy installation of PHP extensions in official PHP Docker images This repository contains a script that can be used to easily install a PHP extension

Michele Locati 2.8k Jan 4, 2023
Silverstripe-sspy - Python based SSPAK export with higher reliability and cross-platform compatibility

SSPY - Python Stand-alone SSPAK solution © Simon Firesphere Erkelens; Moss Mossman Cantwell Usage: sspy [create|load|extract] (db|assets) --file=my.

Simon Erkelens 1 Jun 29, 2021
Sspak - Tool for managing bundles of db/assets from SilverStripe environments

SSPak SSPak is a SilverStripe tool for managing database and assets content, for back-up, restoration, or transfer between environments. The file form

Silverstripe CMS 45 Dec 14, 2022
Markdownfield - Markdown field for SilverStripe

MarkdownField This module introduces a new DB field type Markdown & Markdown Editor. It uses github style Markdown style. And uses the simple markdown

SilverStripers 10 Jul 10, 2022
Automatically delete old SiteTree page versions from Silverstripe

Version truncator for Silverstripe An extension for Silverstripe to automatically delete old versioned DataObject records from your database when a re

Ralph Slooten 35 Dec 7, 2022
Silverstripe-populate - Populate your database through YAML files

Populate Module This module provides a way to populate a database from YAML fixtures and custom classes. For instance, when a building a web applicati

Silverstripe CMS 22 Oct 3, 2022
Silverstripe-ideannotator - Generate docblocks for DataObjects, Page, PageControllers and (Data)Extensions

silverstripe-ideannotator This module generates @property, @method and @mixin tags for DataObjects, PageControllers and (Data)Extensions, so ide's lik

SilverLeague 44 Dec 21, 2022
This module integrates Silverstripe CMS with Google Translate API and then allows content editors to use automatic translation for every translatable field.

Autotranslate This module integrates Silverstripe CMS with Google Translate API and then allows content editors to use automatic translation for every

null 4 Jan 3, 2022
Alerts users in the SilverStripe CMS when multiple people are editing the same page.

Multi-User Editing Alert Alerts users in the SilverStripe CMS when multiple people are editing the same page. Maintainer Contact Julian Seidenberg <ju

Silverstripe CMS 15 Dec 17, 2021