Skip to content

Commit

Permalink
Feature/php8 support (#629)
Browse files Browse the repository at this point in the history
Adds support for PHP8.0, dropping support for PHP7.0 and below.

Backwards incompatible changes:
- Dropped support for php asp tags in templates (removed from php since php7.0)
- Dropped deprecated API calls that where only accessible through SmartyBC
- Dropped support for {php} and {include_php} tags and embedded PHP in templates. Embedded PHP will now be passed through as is.
- Removed all PHP_VERSION_ID and compare_version checks and conditional code blocks that are now no longer required
- Dropped deprecated SMARTY_RESOURCE_CHAR_SET and SMARTY_RESOURCE_DATE_FORMAT constants
- Dropped deprecated Smarty::muteExpectedErrors and Smarty::unmuteExpectedErrors API methods
- Dropped deprecated $smarty->getVariable() method. Use $smarty->getTemplateVars() instead.
- $smarty->registerResource() no longer accepts an array of callback functions

See the changelog for more details.

Switched CI from Travis to Github CI.
  • Loading branch information
wisskid authored Oct 13, 2021
1 parent 9d4f830 commit 39b69f0
Show file tree
Hide file tree
Showing 276 changed files with 3,711 additions and 6,757 deletions.
2 changes: 0 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@

/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/make-release.sh export-ignore
/phpunit.sh export-ignore
/phpunit.xml export-ignore
/TODO.md export-ignore
/travis.ini export-ignore
73 changes: 73 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions

on:
- pull_request
- push

name: CI

jobs:
tests:
name: Tests

runs-on: ${{ matrix.os }}

env:
PHP_EXTENSIONS: dom, json, libxml, mbstring, pdo_sqlite, soap, xml, xmlwriter
PHP_INI_VALUES: assert.exception=1, zend.assertions=1

strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest

php-version:
- "7.1"
- "7.2"
- "7.3"
- "7.4"
- "8.0"

compiler:
- default

include:
- os: ubuntu-latest
php-version: "8.0"
compiler: jit

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Override PHP ini values for JIT compiler
if: matrix.compiler == 'jit'
run: echo "PHP_INI_VALUES::assert.exception=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=1, opcache.optimization_level=-1, opcache.jit=1255, opcache.jit_buffer_size=32M" >> $GITHUB_ENV

- name: Install PHP with extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: pcov
extensions: ${{ env.PHP_EXTENSIONS }}
ini-values: ${{ env.PHP_INI_VALUES }}

- name: Validate composer.json and composer.lock
run: composer validate

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php-version }}-
- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest

- name: Run tests with phpunit
run: ./phpunit.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ utilies/*.php

# Dev
phpunit*
.phpunit.result.cache
vendor/*
composer.lock
39 changes: 0 additions & 39 deletions .travis.yml

This file was deleted.

18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- You can now use `$smarty->muteUndefinedOrNullWarnings()` to activate convert warnings about undefined or null template vars to notices when running PHP8

### Changed
- Switch CI from Travis to Github CI
- Updated unit tests to avoid skipped and risky test warnings

### Removed
- Dropped support for PHP7.0 and below, so Smarty now requires PHP >=7.1
- Dropped support for php asp tags in templates (removed from php since php7.0)
- Dropped deprecated API calls that where only accessible through SmartyBC
- Dropped support for {php} and {include_php} tags and embedded PHP in templates. Embedded PHP will now be passed through as is.
- Removed all PHP_VERSION_ID and compare_version checks and conditional code blocks that are now no longer required
- Dropped deprecated SMARTY_RESOURCE_CHAR_SET and SMARTY_RESOURCE_DATE_FORMAT constants
- Dropped deprecated Smarty::muteExpectedErrors and Smarty::unmuteExpectedErrors API methods
- Dropped deprecated $smarty->getVariable() method. Use $smarty->getTemplateVars() instead.
- $smarty->registerResource() no longer accepts an array of callback functions

## [3.1.40] - 2021-10-13

### Changed
Expand Down
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ $smarty->unregisterFilter(...)

Please refer to the online documentation for all specific changes:

http://www.smarty.net/documentation
https://www.smarty.net/documentation

----

Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# Smarty 3 template engine
[smarty.net](https://www.smarty.net/)

[![Build Status](https://travis-ci.org/smarty-php/smarty.svg?branch=master)](https://travis-ci.org/smarty-php/smarty)
![CI](https://github.com/smarty-php/smarty/workflows/CI/badge.svg)

## Documentation

For documentation see
[www.smarty.net/docs/en/](https://www.smarty.net/docs/en/)

## Requirements

Smarty can be run with PHP 5.2 to PHP 7.4.
Smarty can be run with PHP 7.1 to PHP 8.0.

## Distribution repository

Expand Down Expand Up @@ -74,5 +73,3 @@ Or you could use:
```

Which is a wrapper to install all 3 packages.

Composer can also be used for Smarty2 versions 2.6.24 to 2.6.30.
15 changes: 9 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"keywords": [
"templating"
],
"homepage": "http://www.smarty.net",
"homepage": "https://www.smarty.net",
"license": "LGPL-3.0",
"authors": [
{
Expand All @@ -19,15 +19,18 @@
{
"name": "Rodney Rehm",
"email": "[email protected]"
},
{
"name": "Simon Wisselink",
"homepage": "https://www.iwink.nl/"
}
],
"support": {
"irc": "irc://irc.freenode.org/smarty",
"issues": "https://github.com/smarty-php/smarty/issues",
"forum": "http://www.smarty.net/forums/"
"forum": "https://www.smarty.net/forums/"
},
"require": {
"php": ">=5.2"
"php": "^7.1 || ^8.0"
},
"autoload": {
"classmap": [
Expand All @@ -36,11 +39,11 @@
},
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev"
"dev-master": "4.0.x-dev"
}
},
"require-dev": {
"phpunit/phpunit": "^7.5 || ^6.5 || ^5.7 || ^4.8",
"phpunit/phpunit": "^8.5 || ^7.5",
"smarty/smarty-lexer": "^3.1"
}
}
10 changes: 1 addition & 9 deletions lexer/smarty_internal_templatelexer.plex
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,6 @@ class Smarty_Internal_Templatelexer
textdoublequoted = ~([^"\\]*?)((?:\\.[^"\\]*?)*?)(?=((SMARTYldel)SMARTYal|\$|`\$|"SMARTYliteral))~
namespace = ~([0-9]*[a-zA-Z_]\w*)?(\\[0-9]*[a-zA-Z_]\w*)+~
emptyjava = ~[{][}]~
phptag = ~(SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[/]phpSMARTYrdel~
phpstart = ~[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["']?\s*php\s*["']?\s*[>]|[?][>]|[%][>]~
slash = ~[/]~
ldel = ~(SMARTYldel)SMARTYal~
rdel = ~\s*SMARTYrdel~
Expand Down Expand Up @@ -362,9 +360,6 @@ class Smarty_Internal_Templatelexer
$this->value = substr($this->data,$this->counter,$to-$this->counter);
return false;
}
phptag {
$this->compiler->getTagCompiler('private_php')->parsePhp($this);
}
userliteral {
$this->token = Smarty_Internal_Templateparser::TP_TEXT;
}
Expand All @@ -380,12 +375,9 @@ class Smarty_Internal_Templatelexer
$this->yypushstate(self::TAG);
return true;
}
phpstart {
$this->compiler->getTagCompiler('private_php')->parsePhp($this);
}
char {
if (!isset($this->yy_global_text)) {
$this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS');
$this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal/isS');
}
$to = $this->dataLength;
preg_match($this->yy_global_text, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
Expand Down
11 changes: 0 additions & 11 deletions lexer/smarty_internal_templateparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class Smarty_Internal_Templateparser
{
const ERR1 = 'Security error: Call to private object member not allowed';
const ERR2 = 'Security error: Call to dynamic object member not allowed';
const ERR3 = 'PHP in template not allowed. Use SmartyBC to enable it';

/**
* result status
Expand Down Expand Up @@ -237,16 +236,6 @@ start(res) ::= template. {
res = $this->root_buffer->to_smarty_php($this);
}


// php tags
template ::= template PHP(B). {
$code = $this->compiler->compileTag('private_php',array(array('code' => B), array('type' => $this->lex->phpType )),array());
if ($this->compiler->has_code && !empty($code)) {
$tmp =''; foreach ($this->compiler->prefix_code as $code) {$tmp.=$code;} $this->compiler->prefix_code=array();
$this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp.$code,true)));
}
}

// template text
template ::= template TEXT(B). {
$text = $this->yystack[ $this->yyidx + 0 ]->minor;
Expand Down
8 changes: 2 additions & 6 deletions libs/Autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Smarty_Autoloader
*
* @var array
*/
public static $rootClasses = array('smarty' => 'Smarty.class.php', 'smartybc' => 'SmartyBC.class.php',);
public static $rootClasses = array('smarty' => 'Smarty.class.php');

/**
* Registers Smarty_Autoloader backward compatible to older installations.
Expand Down Expand Up @@ -76,11 +76,7 @@ public static function register($prepend = false)
self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR;
self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR :
self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR;
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
} else {
spl_autoload_register(array(__CLASS__, 'autoload'));
}
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
}

/**
Expand Down
Loading

7 comments on commit 39b69f0

@ophian
Copy link

@ophian ophian commented on 39b69f0 Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wisskid
39b69f0#diff-6bececa4fb8bbffafde9347cc96b9493bdfb2c14426b1b6a89130072ba0e85c2

The second (OR) condition looks very strange to me and is build wrong in my eyes.
If you remove the first condition (¹) $tmp is always undefinied and is build as a triple ternary additionally added by ?? null (for the param I assume) and is a string wriiten as $tmp==='' ? '' ?? null : $tmp to the compile file.
I "think" this second (OR) condition can be removed at all, since the first is alway true EDIT: No, but could be

 $output = '(($tmp = ' . $output . ' ?? null)===null||$tmp===\'\' ? ' . $param . ' : $tmp)';

Some example

{$foo.out.header|default:''}
{$email|default:'No email address available'}
{$title|default:''}
{$smarty.const.FOO|default:''}

result in

string(117) "(($tmp = $_smarty_tpl->tpl_vars['foo']->value['out']['header'] ?? null)===null||$tmp==='' ? '' ?? null : $tmp)"
string(121) "(($tmp = $_smarty_tpl->tpl_vars['email']->value ?? null)===null||$tmp==='' ? 'No email address available' ?? null : $tmp)"
string(99) "(($tmp = $_smarty_tpl->tpl_vars['title']->value ?? null)===null||$tmp==='' ? '' ?? null : $tmp)"
string(73) "(($tmp = @constant('FOO') ?? null)===null||$tmp==='' ? '' ?? null : $tmp)"

or did I miss some special case?

(¹) I still do not like it that way, since that forces users to not care about undefined variable assign, as mentioned somewhere before, but at least it works.

@wisskid
Copy link
Contributor Author

@wisskid wisskid commented on 39b69f0 Aug 7, 2022 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ophian
Copy link

@ophian ophian commented on 39b69f0 Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you didn't get my EDIT, sorry!
I mean it could be

$output = '(($tmp = ' . $output . ' ?? null)===null||$tmp===\'\' ? ' . $param . ' : $tmp)';

@ophian
Copy link

@ophian ophian commented on 39b69f0 Aug 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to add.. I said that $tmp==='' ? '' ?? null : $tmp looks weird, meaning shortform for isset('') ? '' : null in the midpart, doesn't it?!

@wisskid
Copy link
Contributor Author

@wisskid wisskid commented on 39b69f0 Aug 7, 2022 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ophian
Copy link

@ophian ophian commented on 39b69f0 Aug 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm, well I think I was just a little puzzled about that |default:'' part usage, which in the second condition is giving $tmp==='' ? '' ?? null : $tmp.
If you test var_dump('' ?? null); behaviour outside of this context it returns string(0) "" so this (short) ternary is doing nothing.
Forgive the noise and close.

BTW, Did you notice all this space, line and indent changes in the smarty_internal_templatelexer.php diff at here? It looks like it changed worse. Was that intended?

@wisskid
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the lexer is generated code. The generated code is not very pretty.

Please sign in to comment.