Skip to content

Commit

Permalink
Releasing 1.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
technicalguru committed Dec 18, 2020
2 parents 03b90dc + 4140b2d commit 3a04072
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ composer.phar
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock
/composer.lock
/nbproject/private/
51 changes: 45 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This is a collection of useful classes and functions for every day PHP life. It
* Slugifying strings for usage in URLs
* Generating random strings
* Formatting prices and units
* Simple text templating

These classes are no rocket science, just simple helpers that prevent from wiriting the
same code in various flavours over and over again.
Expand Down Expand Up @@ -44,7 +45,7 @@ It is possible to create an object yourself, but it is recommend to use the sing
$request = \TgUtils\Request::getRequest();
```

Inspect the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Request.php) to find out about the various methods available.
Inspect the [source code](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Request.php) to find out about the various methods available.

## Date class

Expand Down Expand Up @@ -74,7 +75,7 @@ $iso8601 = $date->toISO8601();
$someString = $date->format('d.m.Y H:i:s');
```

Inspect the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Date.php) to find out about the various methods available.
Inspect the [source code](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Date.php) to find out about the various methods available.

## Logging

Expand Down Expand Up @@ -174,8 +175,8 @@ Log::clean();
## Authentication Helper
A simple authentication helper interface along with a default implementation is provided:

* [TgUtils\Auth\CredentialsProvider](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Auth/CredentialsProvider.php) - Interface to provide username and password to other objects
* [TgUtils\Auth\DefaultCredentialsProvider](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Auth/DefaultCredentialsProvider.php) - Simple default implementation of the interface
* [TgUtils\Auth\CredentialsProvider](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Auth/CredentialsProvider.php) - Interface to provide username and password to other objects
* [TgUtils\Auth\DefaultCredentialsProvider](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Auth/DefaultCredentialsProvider.php) - Simple default implementation of the interface

## Sensitive Data Obfuscation

Expand Down Expand Up @@ -220,7 +221,45 @@ $emailJavascript = Obfuscation::obfuscateEmail('[email protected]', $id);

Please notice that not all characters are supported in the default character map. It covers mainly
e-mail addresses and phone numbers. However, you can pass your own character set to the obfuscate methods
as third argument. Please consult the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Obfuscation.php) for more details.
as third argument. Please consult the [source code](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Obfuscation.php) for more details.

## Text Templating

To ease the generation of dynamic texts, a template processor is provided. This processor can work on texts that contain variables in
curly brackets `{{variable-definition}}`. The processor knows objects, snippets and formatters.

**Objects** are application objects that hold attributes that you want to be replaced. An object's attribute will be referenced in a template
with `{{objectKey.attributeName}}`, e.g. `{{user.name}}`.

**Snippets** are more complex replacements that will be inserted in your template. This is useful when you need the same complex
text structure in multiple template generations, e.g. for a footer or a header text. Snippets are referenced in a template by
their keys only: `{{snippetKey}}`. A snippet is implemented by the interface [`Snippet`](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Templating/Snippet.php).

**Formatters** can be used to format an object's attribute. Formatters can take parameters to further customize the formatting. A good example
is the [`DateFormatter`](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Templating/DateFormatter.php). The formatter
is referenced with the object's attribute by `{{objectKey.attribute:formatterKey:param1:param2...}}`, e.g. `{{user.created_on:date:rfc822}}`.

All three elements - objects, snippets and formatters - are given to the [`Processor`](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Templating/Processor.php) in its constructor:

```
$objects = array('user' => $myUser);
$snippets = array('header' => new HeaderSnippet(), 'footer' => $new FooterSnippet());
$formatters = array('date' => new DateFormatter());
$language = 'en';
$processor = new Processor($objects, $snippets, $formatters, $language);
```

The language is for information and can be used in snippets or formatters to select the right text.

Finally you can process a template:

```
$template = '{{header}} Hello {{user.name}}! Your account was created on {{user.created_on:date:d/m/Y}}.{{footer}}';
echo $processor->process($template);
// Output is:
// IMPORTANT MESSAGE! Hello John Doe! Your account was created on 02/03/2017. Best regards!
```

## Other Utils
There are some daily tasks that need to be done in applications. The `Utils` class addresses a few of them:
Expand Down Expand Up @@ -264,7 +303,7 @@ $priceString = FormatUtils::formatPrice(3000.643, 'EUR');
$fileSize = FormatUtils::formatUnit(3000643, 'B');
```

Inspect the [source code](https://github.com/technicalguru/php-utils/blob/src/TgUtils/Utils.php) to find more about the methods available.
Inspect the [source code](https://github.com/technicalguru/php-utils/blob/main/src/TgUtils/Utils.php) to find more about the methods available.

# Contribution
Report a bug, request an enhancement or pull request at the [GitHub Issue Tracker](https://github.com/technicalguru/php-utils/issues).
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
"TgLog\\" : "src/TgLog/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"require-dev" : {
"phpunit/phpunit" : "^9"
}
Expand Down
18 changes: 18 additions & 0 deletions src/TgUtils/Templating/CurrencyFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace TgUtils\Templating;

/**
* This formatter takes the currency as a parameter.
*/
class CurrencyFormatter implements Formatter {

public function __construct() {
}

public function format($value, $params, Processor $processor) {
if ($value == NULL) return '';
$currency = count($params) > 0 ? $params[0] : '';
return trim(\TgUtils\FormatUtils::formatPrice($value, $currency, $processor->language, ' '));
}
}
30 changes: 30 additions & 0 deletions src/TgUtils/Templating/DateFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace TgUtils\Templating;

/**
* This formatter takes the format as a parameter and assumes
* the value to any form of Date or parseable date.
*/
class DateFormatter implements Formatter {

public function __construct($timezone = 'UTC') {
$this->timezone = $timezone;
}

public function format($value, $params, Processor $processor) {
if ($value == NULL) return '';
if (!is_object($value) && !is_a($value, 'TgUtils\\Date')) {
$value = new \TgUtils\Date($value, $this->timezone);
}
if (count($params) > 0) {
switch ($params[0]) {
case 'unix': return $value->toUnix();
case 'iso8601': return $value->toISO8601(TRUE);
case 'rfc822': return $value->toRFC822(TRUE);
}
return $value->format(\TgI18n\I18N::_($params[0]), TRUE, TRUE, $processor->language);
}
return $value->__toString();
}
}
16 changes: 16 additions & 0 deletions src/TgUtils/Templating/Formatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace TgUtils\Templating;

/**
* A formatter can format a given value to some software-defined text, using parameters
* and the given processor. The usage of the processor is discouraged but might be required.
*/
interface Formatter {

/**
* Format the given object using the processor and the arguments.
*/
public function format($value, $params, Processor $processor);

}
18 changes: 18 additions & 0 deletions src/TgUtils/Templating/I18nFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace TgUtils\Templating;

/**
* This formatter assumes the value to be an array, an object or a i18n key
* that I18N can process.
*/
class I18nFormatter implements Formatter {

public function __construct() {
}

public function format($value, $params, Processor $processor) {
if ($value == NULL) return '';
return \TgI18n\I18n::_($value, $processor->language);
}
}
148 changes: 148 additions & 0 deletions src/TgUtils/Templating/Processor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php

namespace TgUtils\Templating;

use TgI18n\I18N;

/** Provides some basic templating mechanism */
class Processor {

protected $objects;
protected $snippets;
protected $formatters;
public $language;

/**
* @param array $objects - objects with key => object items
* @param array $snippets - snippets with key => snippet object items
* @param array $formatters - formatters with key => formatter object items
*/
public function __construct($objects = NULL, $snippets = NULL, $formatters = NULL, $language = NULL) {
$this->objects = $objects != NULL ? $objects : array();
$this->snippets = $snippets != NULL ? $snippets : array();
$this->formatters = $formatters != NULL ? $formatters : array();
$this->language = $language != NULL ? $language : \TgI18n\I18N::$defaultLangCode;
}

/**
* Sets the language.
*/
public function setLanguage($language) {
$this->language = $language;
}

/**
* Replace any variables in content with values.
* a variable is a text with {{object.attribute}}
* if attribute is missing, a snippet with this name will be searched
* @param string $s - the content to be processed
*/
public function process($s) {
$rc = '';
$matches = array();
preg_match_all('/{{(.*?)}}/', $s, $matches, PREG_OFFSET_CAPTURE);
$fullMatches = $matches[0];
$slimMatches = $matches[1];
$lastEnd = 0;
for ($i=0; $i<count($fullMatches); $i++) {
$fMatch = $fullMatches[$i];
$sMatch = $slimMatches[$i];
$newStart = $fMatch[1];
$length = strlen($fMatch[0]);
// Take over the plain text since last match
if ($newStart > $lastEnd) $rc .= substr($s, $lastEnd, $newStart-$lastEnd);
// Take over the replacement
$rc .= $this->getVar($sMatch[0]);
// Prepare next iteration
$lastEnd = $newStart + $length;
}
// Finally take the rest
if ($lastEnd < strlen($s)) $rc .= substr($s, $lastEnd);
return $rc;
}

/** Returns the variable with given content definition.
* A variable is a text with object.attribute
* If attribute is missing, a snippet with this name will be searched
*/
protected function getVar($s) {
$parts = explode('.', $s);
$object = $parts[0];
if (count($parts) > 1) return $this->getAttribute($object, $parts[1]);
else {
// Is there a string object?
$object = $this->getObject($object);
if (is_string($object)) return $object;

// Try a snippet
$snippet = $this->getSnippet($object);
if ($snippet != NULL) {
if (is_string($snippet)) return $snippet;
if (is_array($snippet)) return I18N::_($snippet, $this->language);
return $snippet->getOutput($this);
}
}
return '[Not defined: '.$s.']';
}

/**
* Returns the object with the given key or NULL.
*/
public function getObject($name) {
return isset($this->objects[$name]) ? $this->objects[$name] : NULL;
}

/**
* Returns the formatter with the given key or NULL.
*/
public function getFormatter($name) {
return isset($this->formatters[$name]) ? $this->formatters[$name] : NULL;
}

/**
* Returns the snippet with the given key or NULL.
*/
public function getSnippet($name) {
return isset($this->snippets[$name]) ? $this->snippets[$name] : NULL;
}

/**
* Returns the value of the attribute in the object.
* An attribute can have a formatter definition attached e.g. created_on:datetime
* The formatter "datetime" will be used then.
* More arguments for the formatter can follow, separated with : again
*/
public function getAttribute($objName, $attr) {
$object = $this->getObject($objName);
$rc = '';
if ($object != null) {
// Split attributeName from format instructions
$attrDef = explode(':', $attr);
$attrName = array_shift($attrDef);
$attrFormat = count($attrDef) > 0 ? array_shift($attrDef) : 'plain';
if (isset($object->$attrName)) {
$value = $object->$attrName;
$rc = '';
// check formatting
if ($attrFormat != 'plain') {
$formatter = $this->getFormatter($attrFormat);
if ($formatter != NULL) {
$rc = $formatter->format($value, $attrDef, $this);
}
} else if (is_object($value)) {
if (is_a($value, 'TgUtils\\Date')) {
$formatter = $this->getFormatter('date');
if ($formatter == NULL) $formatter = new DateFormatter();
$rc = $formatter->format($value, $attrDef, $this);
} else {
$rc = $value->__toString();
}
} else {
$rc = $value;
}
}
}
return $rc;
}

}
16 changes: 16 additions & 0 deletions src/TgUtils/Templating/Snippet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace TgUtils\Templating;

/**
* A snippet is a fixed, software-defined piece of text that can be inserted in
* templates via the {{template-name}} variable.
*/
interface Snippet {

/**
* Return the output of the template, using the given processor for objects and formatters.
*/
public function getOutput(Processor $processor);

}
Loading

0 comments on commit 3a04072

Please sign in to comment.