Skip to content

Commit

Permalink
Merge pull request #21 from rawsrc/6.0.0
Browse files Browse the repository at this point in the history
New version 6.0.0
  • Loading branch information
rawsrc authored Aug 12, 2023
2 parents 4781470 + 3049d72 commit 53f8070
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 494 deletions.
482 changes: 146 additions & 336 deletions PhpEcho.php

Large diffs are not rendered by default.

97 changes: 21 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# **PhpEcho**

`2023-05-09` `PHP 8.0+` `v.5.4.2`
`2023-08-12` `PHP 8.0+` `6.0.0`

## **A native PHP template engine : One class to rule them all**
## **VERSION 5.X IS ONLY FOR PHP 8 AND ABOVE**
## **IS ONLY FOR PHP 8 AND ABOVE**

When you develop a web application, the rendering of views may be a real challenge.
Especially if you just want to use only native PHP syntax and avoid external templating language.

This is exactly the goal of `PhpEcho`: providing a pure PHP template engine with no other dependencies.<br>
This is exactly the goal of `PhpEcho`: providing a pure NATIVE PHP TEMPLATE ENGINE with no other dependencies.<br>

`PhpEcho` is very simple to use, it's very close to the native PHP way of rendering HTML/CSS/JS.<br>
It is based on an OOP approach using only one class to get the job done.<br>
Expand All @@ -35,68 +35,6 @@ The class will manage :
```bash
composer require rawsrc/phpecho
```
**Changelog v5.4.1:**<br>
1. Minor bugfix in method `isArrayOfPhpEchoBlocks(mixed $p)` when `$p` is an empty array

**Changelog v5.4.0:**<br>
1. Add new abstract class `ViewBuilder` that help to manipulate abstract views as objects

**Changelog v5.3.1:**<br>
1. Add option to return natively `null` when a key doesn't exist instead of throwing an `Exception`
By default this option is not activated. To activate, use: `PhpEcho::setNullIfNotExist(true);`; to deactivate,
use: `PhpEcho::setNullIfNotExist(false);`

**Changelog v5.3.0:**<br>
1. Code optimization and improvement of the parameters management
2. The method `hasGlobalParam(string $name)` is now `static`
3. You can now define the seek order to get the first value either
from the `local` or `global` context using `getAnyParam(string $name, string $seek_order = 'local'): mixed`
4. It's possible to set at once a parameter into the local and global context using `setAnyParam(string $name, mixed $value)`
4. It's possible to unset at once a parameter from the local and the global context using `unsetAnyParam(string $name)`<br>
Test files are updated

**Changelog v5.2.1:**<br>
1. Improving the local and global parameters' management<br>
Add new method `getAnyParam(string $name)` that will return first the local value of the parameter if defined
or the global value instead or throw finally an exception if the parameter is unknown<br>
Offers the possibility to unset any local or global parameter using `unsetParam(string $name)` or `unsetGlobalParam(string $name)`<br>
You can now check if a parameter is defined either in the local or global array using `hasAnyParam(string $name)`<br>
Test files are updated

**Changelog v5.2.0:**<br>
1. Space is not used as directory separator anymore, the only admitted directory separator is now / (slash)
Space is now preserved in the filepath.
Everywhere you wrote for example `new PhpEcho('block dummy_block.php');`, you must replace it with `new PhpEcho('block/dummy_block.php');`
The same thing for `$this->renderblock('block dummy_block.php');` which must be replaced by `$this->renderBlock('block/dummy_block.php');`
and also for `this->renderByDefault('preloader', 'block preloader.php')` which become `this->renderByDefault('preloader', 'block/preloader.php')`
If you have previously used a space as directory separator, you'll have to review all the view files.
If you stayed stuck with slash (/), no problems, this upgrade won't impact your code.

**Changelog v5.1.1:**<br>
1. Standard helpers are now injected once automatically

**Changelog v5.1.0:**<br>
1. The method `getHelper(string $name): Closure` is not static anymore
2. The equivalent static is now defined as `getHelperBase(string $name): Closure`
3. The method `isHelper(string $name): bool` does not throw any `Exception` anymore and only returns a strict boolean
4. Internally some code optimization and better logic segmentation: new method `getHelperDetails(string $name): array`

**Changelog v5.0.0:**<br>
1. Removing th constant `HELPER_BOUND_TO_CLASS_INSTANCE`, it's replaced by `PhpEcho::addBindableHelper`
2. Removing the constant `HELPER_RETURN_ESCAPED_DATA`. Now, the engine is able to check when data must
be escaped and preserve the native datatype when it's safe in HTML context
2. Instead of dying silently with `null` or empty string, the engine now throws in all case an `Exception`
You must produce a better code as it will crash on each low quality segment.
3. Add new method `renderBlock()` to link easily a child block to its parent
4. Many code improvements
5. Fully tested: the core and all helpers have been fully tested
6. Add new helper to the standard library `renderIfNotSet()` that render a default value instead
of throwing an `Exception` for any missing key in the stored key-value pairs

**NEW VERSION PhpEcho v5.0.0:**<br>
This version is a major update and breaks the compatibility with the code
written for the previous version of the engine. The changes impact mainly the code
generating the helpers. The code for the view part of your project is not impacted by the upgrade.

**What you must know to use it**
1. All values read from a PhpEcho instance are escaped and safe in HTML context.
Expand Down Expand Up @@ -269,7 +207,7 @@ In the layout, some values are required:
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="<?= $this['description]'] ?>">
<meta name="description" content="<?= $this['description'] ?>">
<title><?= $this['title'] ?></title>
</head>
<body>
Expand Down Expand Up @@ -368,27 +306,34 @@ This way, you do not cut the tree ;-)

**AUTO WIRING VARS**

The engine fills the vars attached to a block automatically if there's no other values defined.
In that case the child gets a copy of the vars defined in the parent block.
```php
<?php
Coming from versions prior to 6, this change may slightly break your existing code.
Before, the engine used to copy the vars from the parent block to its child only when the child had
no vars defined at all. Now, you must provide the values expected to be rendered by the current block,
there's no more copy.

As many developers, I usually store all the needed values in the root and then I used to create my blocks without
defining specific values, so the child blocks got a copy of the parent values and so on.

declare(strict_types=1);
This is exactly the new approach.

Now if the value is not defined/found in the current block, then the engine will automatically seek for it in the root of the tree.
You can store all the values needed by the child blocks in the root and let the engine pick them up on rendering.
```php
<?php declare(strict_types=1);

use rawsrc\PhpEcho\PhpEcho;

// $page is the root of the tree
$page = new PhpEcho('layout/main.php');
$page['title'] = 'My first use case of PhpEcho';
$page['description'] = 'PhpEcho, PHP template engine, easy to learn and use';
$page['login'] = 'rawsrc';
$page['url_submit'] = 'any/path/for/connection';

// no vars are attached to the block as the second parameter is omitted
$body = new PhpEcho('block login.php'); // login expects 2 values (login and url_submit)
$body = new PhpEcho('block/login.php'); // login expects 2 values (login and url_submit)

// when we inject the block into the parent, the auto-wiring will automatically
// pass a copy of parent's vars to the child
$page['body'] = $body; // $body['login'] and $body['url_submit'] are well defined
$page['body'] = $body; // $body['login'] and $body['url_submit'] are well-defined
// both are sought from the $page block (root)

echo $page;
```
Expand Down
27 changes: 1 addition & 26 deletions ViewBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,61 +36,36 @@
class ViewBuilder
implements ArrayAccess
{
/**
* @return PhpEcho
*/
abstract public function build(): PhpEcho;

public array $data = [];

/**
* @return array
*/
public function getData(): array
{
return $this->data;
}

/**
* @return string
*/
public function __toString(): string
{
return (string)$this->build();
}

//region ARRAY ACCESS
/**
* @param mixed $offset
* @param mixed $value
*/
//region ARRAY ACCESS INTERFACE
public function offsetSet(mixed $offset, mixed $value): void
{
$this->data[$offset] = $value;
}

/**
* @param mixed $offset
* @return mixed
*/
public function offsetGet(mixed $offset): mixed
{
return $this->data[$offset];
}

/**
* @param $offset
* @return bool
*/
public function offsetExists($offset): bool
{
return array_key_exists($offset, $this->data);
}

/**
* @param mixed $offset
* @return void
*/
public function offsetUnset(mixed $offset): void
{
unset ($this->data[$offset]);
Expand Down
76 changes: 76 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# **PhpEcho**

**Changelog 6.0.0**<br>
1. Code refactoring
2. As PHP is now a pretty self-describing and self-documenting language, the quantity of PHPDoc is now heavily reduced
3. Removed feature: space notation for arrays. Any space in a key is now preserved, the engine doesn't interpret them as sub-arrays anymore
5. New feature: management of local and global vars, please note that the local always override the global ones
3. New feature: defining global values that will be available through the whole tree of blocks using: `injectVars(array $vars)`
4. New feature: defining local values after instantiating a `PhpEcho` block at once using: `setVars(array $p)`
6. Internal heavy change: there's no more copy of variables between blocks (reduce the memory footprint and increase the global performance)
7. If the current block is not able to provide a value to be rendered then the engine will automatically seek for it in the root of the tree
8. Better management of values composed of nested array
9. Cloning a `PhpEcho` block is now possible, the cloned value keeps everything but the link to its parent block. The new one is orphan

**Changelog 5.4.1:**<br>
1. Minor bugfix in method `isArrayOfPhpEchoBlocks(mixed $p)` when `$p` is an empty array

**Changelog 5.4.0:**<br>
1. Add new abstract class `ViewBuilder` that help to manipulate abstract views as objects

**Changelog 5.3.1:**<br>
1. Add option to return natively `null` when a key doesn't exist instead of throwing an `Exception`
By default this option is not activated. To activate, use: `PhpEcho::setNullIfNotExist(true);`; to deactivate,
use: `PhpEcho::setNullIfNotExist(false);`

**Changelog 5.3.0:**<br>
1. Code optimization and improvement of the parameters management
2. The method `hasGlobalParam(string $name)` is now `static`
3. You can now define the seek order to get the first value either
from the `local` or `global` context using `getAnyParam(string $name, string $seek_order = 'local'): mixed`
4. It's possible to set at once a parameter into the local and global context using `setAnyParam(string $name, mixed $value)`
4. It's possible to unset at once a parameter from the local and the global context using `unsetAnyParam(string $name)`<br>
Test files are updated

**Changelog 5.2.1:**<br>
1. Improving the local and global parameters' management<br>
Add new method `getAnyParam(string $name)` that will return first the local value of the parameter if defined
or the global value instead or throw finally an exception if the parameter is unknown<br>
Offers the possibility to unset any local or global parameter using `unsetParam(string $name)` or `unsetGlobalParam(string $name)`<br>
You can now check if a parameter is defined either in the local or global array using `hasAnyParam(string $name)`<br>
Test files are updated

**Changelog 5.2.0:**<br>
1. Space is not used as directory separator anymore, the only admitted directory separator is now / (slash)
Space is now preserved in the filepath.
Everywhere you wrote for example `new PhpEcho('block dummy_block.php');`, you must replace it with `new PhpEcho('block/dummy_block.php');`
The same thing for `$this->renderblock('block dummy_block.php');` which must be replaced by `$this->renderBlock('block/dummy_block.php');`
and also for `this->renderByDefault('preloader', 'block preloader.php')` which become `this->renderByDefault('preloader', 'block/preloader.php')`
If you have previously used a space as directory separator, you'll have to review all the view files.
If you stayed stuck with slash (/), no problems, this upgrade won't impact your code.

**Changelog 5.1.1:**<br>
1. Standard helpers are now injected once automatically

**Changelog 5.1.0:**<br>
1. The method `getHelper(string $name): Closure` is not static anymore
2. The equivalent static is now defined as `getHelperBase(string $name): Closure`
3. The method `isHelper(string $name): bool` does not throw any `Exception` anymore and only returns a strict boolean
4. Internally some code optimization and better logic segmentation: new method `getHelperDetails(string $name): array`

**Changelog 5.0.0:**<br>
1. Removing th constant `HELPER_BOUND_TO_CLASS_INSTANCE`, it's replaced by `PhpEcho::addBindableHelper`
2. Removing the constant `HELPER_RETURN_ESCAPED_DATA`. Now, the engine is able to check when data must
be escaped and preserve the native datatype when it's safe in HTML context
2. Instead of dying silently with `null` or empty string, the engine now throws in all case an `Exception`
You must produce a better code as it will crash on each low quality segment.
3. Add new method `renderBlock()` to link easily a child block to its parent
4. Many code improvements
5. Fully tested: the core and all helpers have been fully tested
6. Add new helper to the standard library `renderIfNotSet()` that render a default value instead
of throwing an `Exception` for any missing key in the stored key-value pairs

**Changelog 5.0.0:**<br>
This version is a major update and breaks the compatibility with the code
written for the previous version of the engine. The changes impact mainly the code
generating the helpers. The code for the view part of your project is not impacted by the upgrade.
35 changes: 1 addition & 34 deletions stdPhpEchoHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
//region is_scalar
/**
* This is a standalone helper
*
* @param mixed $p
* @return bool
*/
$is_scalar = function(mixed $p): bool {
return is_scalar($p) || (is_object($p) && method_exists($p, '__toString'));
Expand All @@ -19,9 +16,6 @@
//region to_escape
/**
* Check if the value in parameter should be escaped or not
*
* @param mixed $p
* @return bool
*/
$to_escape = function(mixed $p): bool {
if (is_string($p)) {
Expand All @@ -46,9 +40,6 @@
*
* This is a standalone helper that is not directly accessible
* Use instead the common helper 'hsc' which is compatible with arrays
*
* @param array $part
* @return array
*/
$hsc_array = function(array $part) use (&$hsc_array, $to_escape): array {
$data = [];
Expand Down Expand Up @@ -79,9 +70,6 @@
* - true bool, true int, true float, PhpEcho instance, object without __toString()
*
* Otherwise, the value is cast to string and escaped
*
* @param mixed $p
* @return array|string
*/
$hsc = function(mixed $p) use ($hsc_array, $is_scalar): array|string {
if ($p instanceof PhpEcho) {
Expand Down Expand Up @@ -110,8 +98,6 @@
* if $key = 'abc def' then the engine will search for
* the value as $vars['abc']['def']
*
* @param string $key
* @return mixed
* @throws InvalidArgumentException
*/
$raw = function(string $key): mixed {
Expand All @@ -122,11 +108,6 @@
//endregion raw

//region render_if_not_set
/**
* @param string $key
* @param mixed $default_value
* @return mixed
*/
$render_if_not_set = function(string $key, mixed $default_value) use ($hsc): mixed {
/** @var PhpEcho $this */
try {
Expand All @@ -149,9 +130,6 @@
* If $strict_match === false then if the current key is not found in the parent block, then the search will continue
* until reaching the root or stop at the first match
*
* @param string|array $keys
* @param bool $strict_match
* @return mixed
* @throws InvalidArgumentException If not found
*/
$key_up = function(array|string $keys, bool $strict_match = true) use ($to_escape, $hsc): mixed {
Expand Down Expand Up @@ -189,9 +167,6 @@
//endregion key_up

//region root
/**
* @return PhpEcho
*/
$root = function(): PhpEcho {
// climbing to the root
/** @var PhpEcho $block */
Expand All @@ -213,9 +188,7 @@
* A string will be split in parts using the space for delimiter
* If one of the keys contains a space, use an array of keys instead
*
* @param array|string $keys
* @return mixed
* @throws InvalidArgumentException If not found
* @throws InvalidArgumentException
*/
$root_var = function(array|string $keys) use ($to_escape, $hsc): mixed {
/** @var PhpEcho $this */
Expand Down Expand Up @@ -250,8 +223,6 @@
/**
* Seek the parameter from the current block to the root
*
* @param string $name
* @return null
* @throws InvalidArgumentException If not found
*/
$seek_param = function(string $name): mixed {
Expand All @@ -276,10 +247,6 @@
/**
* Return the html attribute "selected" if $p == $ref
* This is a standalone helper
*
* @param mixed $p scalar value to check
* @param mixed $ref scalar value ref
* @return string
*/
$selected = function(mixed $p, mixed $ref) use ($is_scalar): string {
return $is_scalar($p) && $is_scalar($ref) && ((string)$p === (string)$ref) ? ' selected ' : '';
Expand Down
Loading

0 comments on commit 53f8070

Please sign in to comment.