Skip to content

Commit

Permalink
feat: Upgrade Pico to PHP 8.2/8.3
Browse files Browse the repository at this point in the history
Make Pico compatible with PHP 8.2 and 8.3.

- Upgrade symfony/yaml config reader
- Upgrade twig template engine,
- Raise supported PHP version,
- Remove pico/pico-deprecated
- Remove redundant index files
- Use pico-composer to set up a project

Required Changes for users running version 2.1:

- Replace composer.json from pico/pico-composer to load Pico Core via Composer
- Add all required folders to project root (config/, plugins/, themes/)
- Convert config file from PHP to YAML
  - Errors may happen due to wrong value types (eg. multiline text is not supported)
- Themes may need some tweaks:
  - Themes need a YAML config as well
  - HTML files in themes need to be renamed to TWIG files
  - Replace twig condition »is_front_page« with »current_page.id == "index"«
  - Replace twig variable »page.excerpt« with »page.meta.Summary«
  • Loading branch information
pixelbrackets committed Oct 22, 2024
1 parent 09aa825 commit d4324bb
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 40 deletions.
13 changes: 3 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@
"source": "https://github.com/picocms/Pico"
},
"require": {
"php": ">=5.3.6",
"php": ">=8.2.20",
"ext-mbstring": "*",
"twig/twig": "^1.36",
"symfony/yaml" : "^2.8",
"twig/twig": "^3.14",
"symfony/yaml" : "^7.1",
"erusev/parsedown": "1.8.0-beta-7",
"erusev/parsedown-extra": "0.8.0-beta-1"
},
"suggest": {
"picocms/pico-theme": "Pico requires a theme to actually display the contents of your website. This is Pico's official default theme.",
"picocms/pico-deprecated": "PicoDeprecated's purpose is to maintain backward compatibility to older versions of Pico.",
"picocms/composer-installer": "This Composer plugin is responsible for installing Pico plugins and themes using the Composer package manager."
},
"autoload": {
Expand All @@ -49,11 +48,5 @@
"PicoPluginInterface": "lib/",
"AbstractPicoPlugin": "lib/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev",
"dev-pico-3.0": "3.0.x-dev"
}
}
}
16 changes: 8 additions & 8 deletions lib/Pico.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ class Pico
* Twig instance used for template parsing
*
* @see Pico::getTwig()
* @var Twig_Environment|null
* @var \TwigEnvironment|null
*/
protected $twig;

Expand Down Expand Up @@ -2092,30 +2092,30 @@ public function getPageTree()
* {@see PicoTwigExtension} Twig extension.
*
* @see Pico::getTwig()
* @see https://twig.symfony.com/ Twig website
* @see http://twig.sensiolabs.org/ Twig website
* @see https://github.com/twigphp/Twig Twig on GitHub
*
* @return Twig_Environment|null Twig template engine
* @return \TwigEnvironment|null Twig template engine
*/
public function getTwig()
{
if ($this->twig === null) {
$twigConfig = $this->getConfig('twig_config');

$twigLoader = new Twig_Loader_Filesystem($this->getThemesDir() . $this->getTheme());
$this->twig = new Twig_Environment($twigLoader, $twigConfig);
$twigLoader = new \Twig\Loader\FilesystemLoader($this->getThemesDir() . $this->getTheme());
$this->twig = new \Twig\Environment($twigLoader, $twigConfig);
$this->twig->addExtension(new PicoTwigExtension($this));

if (!empty($twigConfig['debug'])) {
$this->twig->addExtension(new Twig_Extension_Debug());
$this->twig->addExtension(new \Twig\Extension\DebugExtension());
}

// register content filter
// we pass the $pages array by reference to prevent multiple parser runs for the same page
// this is the reason why we can't register this filter as part of PicoTwigExtension
$pico = $this;
$pages = &$this->pages;
$this->twig->addFilter(new Twig_SimpleFilter(
$this->twig->addFilter(new \Twig\TwigFilter(
'content',
function ($page) use ($pico, &$pages) {
if (isset($pages[$page])) {
Expand Down Expand Up @@ -2156,7 +2156,7 @@ protected function getTwigVariables()
'theme_url' => $this->getConfig('themes_url') . $this->getTheme(),
'site_title' => $this->getConfig('site_title'),
'meta' => $this->meta,
'content' => new Twig_Markup($this->content, 'UTF-8'),
'content' => new \Twig\Markup($this->content, 'UTF-8'),
'pages' => $this->pages,
'previous_page' => $this->previousPage,
'current_page' => $this->currentPage,
Expand Down
44 changes: 22 additions & 22 deletions lib/PicoTwigExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* @license http://opensource.org/licenses/MIT The MIT License
* @version 2.1
*/
class PicoTwigExtension extends Twig_Extension
class PicoTwigExtension extends \Twig\Extension\AbstractExtension
{
/**
* Current instance of Pico
Expand Down Expand Up @@ -53,7 +53,7 @@ public function getPico()
/**
* Returns the name of the extension
*
* @see Twig_ExtensionInterface::getName()
* @see \Twig\Extension\AbstractExtension::getName()
*
* @return string the extension name
*/
Expand All @@ -65,38 +65,38 @@ public function getName()
/**
* Returns a list of Pico-specific Twig filters
*
* @see Twig_ExtensionInterface::getFilters()
* @see \Twig\Extension\ExtensionInterface::getFilters()
*
* @return Twig_SimpleFilter[] array of Pico's Twig filters
* @return \Twig\TwigFilter[] array of Pico's Twig filters
*/
public function getFilters()
{
return array(
'markdown' => new Twig_SimpleFilter(
'markdown' => new \Twig\TwigFilter(
'markdown',
array($this, 'markdownFilter'),
array('is_safe' => array('html'))
),
'map' => new Twig_SimpleFilter('map', array($this, 'mapFilter')),
'sort_by' => new Twig_SimpleFilter('sort_by', array($this, 'sortByFilter')),
'link' => new Twig_SimpleFilter('link', array($this->pico, 'getPageUrl')),
'url' => new Twig_SimpleFilter('url', array($this->pico, 'substituteUrl'))
'map' => new \Twig\TwigFilter('map', array($this, 'mapFilter')),
'sort_by' => new \Twig\TwigFilter('sort_by', array($this, 'sortByFilter')),
'link' => new \Twig\TwigFilter('link', array($this->pico, 'getPageUrl')),
'url' => new \Twig\TwigFilter('url', array($this->pico, 'substituteUrl'))
);
}

/**
* Returns a list of Pico-specific Twig functions
*
* @see Twig_ExtensionInterface::getFunctions()
* @see \Twig\Extension\ExtensionInterface::getFunctions()
*
* @return Twig_SimpleFunction[] array of Pico's Twig functions
* @return \Twig\TwigFunction[] array of Pico's Twig functions
*/
public function getFunctions()
{
return array(
'url_param' => new Twig_SimpleFunction('url_param', array($this, 'urlParamFunction')),
'form_param' => new Twig_SimpleFunction('form_param', array($this, 'formParamFunction')),
'pages' => new Twig_SimpleFunction('pages', array($this, 'pagesFunction'))
'url_param' => new \Twig\TwigFunction('url_param', array($this, 'urlParamFunction')),
'form_param' => new \Twig\TwigFunction('form_param', array($this, 'formParamFunction')),
'pages' => new \Twig\TwigFunction('pages', array($this, 'pagesFunction'))
);
}

Expand Down Expand Up @@ -136,12 +136,12 @@ public function markdownFilter($markdown, array $meta = array(), $singleLine = f
*
* @return array mapped values
*
* @throws Twig_Error_Runtime
* @throws \Twig\Error\RuntimeError
*/
public function mapFilter($var, $mapKeyPath)
{
if (!is_array($var) && (!is_object($var) || !($var instanceof Traversable))) {
throw new Twig_Error_Runtime(sprintf(
throw new \Twig\Error\RuntimeError(sprintf(
'The map filter only works with arrays or "Traversable", got "%s"',
is_object($var) ? get_class($var) : gettype($var)
));
Expand Down Expand Up @@ -178,20 +178,20 @@ public function mapFilter($var, $mapKeyPath)
*
* @return array sorted array
*
* @throws Twig_Error_Runtime
* @throws \Twig\Error\RuntimeError
*/
public function sortByFilter($var, $sortKeyPath, $fallback = 'bottom')
{
if (is_object($var) && ($var instanceof Traversable)) {
$var = iterator_to_array($var, true);
} elseif (!is_array($var)) {
throw new Twig_Error_Runtime(sprintf(
throw new \Twig\Error\RuntimeError(sprintf(
'The sort_by filter only works with arrays or "Traversable", got "%s"',
is_object($var) ? get_class($var) : gettype($var)
));
}
if (($fallback !== 'top') && ($fallback !== 'bottom') && ($fallback !== 'keep') && ($fallback !== "remove")) {
throw new Twig_Error_Runtime(
throw new \Twig\Error\RuntimeError(
'The sort_by filter only supports the "top", "bottom", "keep" and "remove" fallbacks'
);
}
Expand Down Expand Up @@ -399,7 +399,7 @@ public function formParamFunction($name, $filter = '', $options = null, $flags =
* returns Pico's full pages array.
*
* If `$depth` is negative after taking `$offset` into consideration, the
* function will throw a {@see Twig_Error_Runtime} exception, since this
* function will throw a {@see \Twig\Error\RuntimeError} exception, since this
* would simply make no sense and is likely an error. Passing a negative
* `$depthOffset` is equivalent to passing `$depthOffset = 0`.
*
Expand All @@ -421,7 +421,7 @@ public function formParamFunction($name, $filter = '', $options = null, $flags =
*
* @return array[] the data of the matched pages
*
* @throws Twig_Error_Runtime
* @throws \Twig\Error\RuntimeError
*/
public function pagesFunction($start = '', $depth = 0, $depthOffset = 0, $offset = 1)
{
Expand All @@ -443,7 +443,7 @@ public function pagesFunction($start = '', $depth = 0, $depthOffset = 0, $offset
$depthOffset = $depthOffset + $offset;

if (($depth !== null) && ($depth < 0)) {
throw new Twig_Error_Runtime('The pages function doesn\'t support negative depths');
throw new \Twig\Error\RuntimeError('The pages function doesn\'t support negative depths');
}

$pageTree = $this->getPico()->getPageTree();
Expand Down

0 comments on commit d4324bb

Please sign in to comment.