316 lines
8.1 KiB
PHP
Executable File
316 lines
8.1 KiB
PHP
Executable File
<?php
|
|
|
|
namespace Franzz\Objects;
|
|
use \Settings;
|
|
|
|
/**
|
|
* Mask Reader
|
|
* @author franzz
|
|
* @version 1.2
|
|
*/
|
|
class Mask extends PhpObject
|
|
{
|
|
public $sMaskName;
|
|
public $sFilePath;
|
|
private $sMask;
|
|
private $asTags;
|
|
private $asTagsParams;
|
|
private $asPartsSource;
|
|
private $aoInstances;
|
|
|
|
private $oLang;
|
|
private $sTimezone;
|
|
|
|
const MASK_FOLDER = 'masks/';
|
|
const MASK_EXT = '.html';
|
|
const START_TAG = 'START';
|
|
const END_TAG = 'END';
|
|
const TAG_MARK = '[#]';
|
|
const LANG_PREFIX = 'lang:';
|
|
const TIME_PREFIX = 'time:';
|
|
|
|
public function __construct($sFileName='', Translator $oLang=null, $sTimezone = '')
|
|
{
|
|
//init
|
|
parent::__construct(__CLASS__);
|
|
$this->sMaskName = '';
|
|
$this->sFilePath = '';
|
|
$this->sMask = '';
|
|
$this->asTags = array();
|
|
$this->asTagsParams = array();
|
|
$this->asPartsSource = array();
|
|
$this->aoInstances = array();
|
|
$this->sFilePath = '';
|
|
$this->setTranslator($oLang);
|
|
$this->setTimezone($sTimezone);
|
|
|
|
//load file
|
|
if($sFileName!='') $this->initFile($sFileName);
|
|
}
|
|
|
|
public function setLanguage($sLang, $sDefaultLang='') {
|
|
if(is_null($this->oLang)) $this->setTranslator(new Translator($sLang, $sDefaultLang));
|
|
else {
|
|
$this->oLang->setLanguage($sLang, $sDefaultLang);
|
|
foreach($this->aoInstances as &$aoPartInstance) {
|
|
foreach($aoPartInstance as $oInstance) $oInstance->setLanguage($sLang, $sDefaultLang);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function setTimezone($sTimezone) {
|
|
$this->sTimezone = ($sTimezone=='')?Settings::TIMEZONE:$sTimezone;
|
|
}
|
|
|
|
private function setTranslator($oLang) {
|
|
$this->oLang = $oLang;
|
|
foreach($this->aoInstances as &$aoPartInstance) {
|
|
foreach($aoPartInstance as $oInstance) $oInstance->setTranslator($this->oLang);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Mask Translator
|
|
* @return Translator
|
|
*/
|
|
public function getTranslator() {
|
|
return $this->oLang;
|
|
}
|
|
|
|
public static function getMaskFile($sFileName)
|
|
{
|
|
return self::MASK_FOLDER.$sFileName.self::MASK_EXT;
|
|
}
|
|
|
|
public function initFile($sFileName)
|
|
{
|
|
$sFilePath = self::getMaskFile(basename($sFileName));
|
|
if(file_exists($sFilePath))
|
|
{
|
|
$this->sFilePath = $sFilePath;
|
|
$sSource = file_get_contents($this->sFilePath);
|
|
$this->initMask($sFileName, $sSource);
|
|
}
|
|
else
|
|
{
|
|
$this->addError('Fichier introuvable à l\'adresse : '.$sFilePath);
|
|
}
|
|
}
|
|
|
|
public function initFileFromString($sSource, $sPartName='', $iInstanceNb=0)
|
|
{
|
|
$this->initMask($sPartName.' (from row) '.$iInstanceNb, $sSource);
|
|
}
|
|
|
|
private function initMask($sMaskName, $sSource)
|
|
{
|
|
$this->sMaskName = $sMaskName;
|
|
$this->sMask = $sSource;
|
|
$this->setParts();
|
|
$this->setDefaultTagValues();
|
|
}
|
|
|
|
private function setParts()
|
|
{
|
|
while(preg_match('/\<\!-- \[PART\] (?P<part>\S+) \[START\] --\>/u', $this->sMask, $asMatch))
|
|
{
|
|
$sPartName = $asMatch['part'];
|
|
|
|
$this->asPartsSource[$sPartName] = $this->getCleanPart($sPartName);
|
|
$this->aoInstances[$sPartName] = array();
|
|
}
|
|
}
|
|
|
|
private function getCleanPart($sPartName)
|
|
{
|
|
$iStartPos = $this->getPartStartPos($sPartName);
|
|
$iEndPos = $this->getPartEndPos($sPartName);
|
|
$sPart = mb_substr($this->sMask, $iStartPos, $iEndPos-$iStartPos);
|
|
$sExtendedPart = $this->getPartPattern($sPartName, self::START_TAG).$sPart. $this->getPartPattern($sPartName, self::END_TAG);
|
|
$this->sMask = str_replace($sExtendedPart, $this->getPartTagPattern($sPartName), $this->sMask);
|
|
return $sPart;
|
|
}
|
|
|
|
private function getPartStartPos($sPartName)
|
|
{
|
|
$sPartStartPattern = $this->getPartPattern($sPartName, self::START_TAG);
|
|
return mb_strpos($this->sMask, $sPartStartPattern) + strlen($sPartStartPattern);
|
|
}
|
|
|
|
private function getPartEndPos($sPartName)
|
|
{
|
|
$sPartEndPattern = $this->getPartPattern($sPartName, self::END_TAG);
|
|
return mb_strpos($this->sMask, $sPartEndPattern);
|
|
}
|
|
|
|
private function getPartPattern($sPartName, $sAction)
|
|
{
|
|
return '<!-- [PART] '.$sPartName.' ['.$sAction.'] -->';
|
|
}
|
|
|
|
private function getPartTagPattern($sPartName, $bMark=true)
|
|
{
|
|
$sPartTag = 'PART '.$sPartName;
|
|
return $bMark?$this->addTagMark($sPartTag):$sPartTag;
|
|
}
|
|
|
|
public function addInstance($sPartName, $asTags)
|
|
{
|
|
$this->newInstance($sPartName);
|
|
foreach($asTags as $sTagName=>$sTagValue)
|
|
{
|
|
$this->setInstanceTag($sPartName, $sTagName, $sTagValue);
|
|
}
|
|
}
|
|
|
|
public function newInstance($sPartName)
|
|
{
|
|
//Finding the part ($oMask is a pointer)
|
|
$oMask = $this->findPart($this, $sPartName);
|
|
if(!$oMask) $this->addError('No part found : '.$sPartName);
|
|
|
|
//Retrieving source html
|
|
$sPartSource = $oMask->asPartsSource[$sPartName];
|
|
|
|
//Creating new instance
|
|
$oInstance = new Mask('', $this->oLang);
|
|
$oInstance->initFileFromString($sPartSource, $sPartName);
|
|
$oMask->aoInstances[$sPartName][] = $oInstance;
|
|
}
|
|
|
|
public function setInstanceTag($sPartName, $sTagName, $sTagValue, $asTagParams=array())
|
|
{
|
|
$oMask = $this->findPart($this, $sPartName);
|
|
if(!$oMask) $this->addError('No part found : '.$sPartName);
|
|
|
|
$oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue, $asTagParams);
|
|
}
|
|
|
|
public function setInstanceTags($sPartName, $asTags)
|
|
{
|
|
$oMask = $this->findPart($this, $sPartName);
|
|
if(!$oMask) $this->addError('No part found : '.$sPartName);
|
|
|
|
foreach($asTags as $sTagName=>$sTagValue) {
|
|
$oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue);
|
|
}
|
|
}
|
|
|
|
private function findPart($oMask, $sPartName)
|
|
{
|
|
if(array_key_exists($sPartName, $oMask->aoInstances))
|
|
{
|
|
return $oMask;
|
|
}
|
|
else //going deeper to find the part
|
|
{
|
|
foreach($oMask->aoInstances as $sLevelPartName=>$aoInstances)
|
|
{
|
|
if(!empty($aoInstances))
|
|
{
|
|
//take last instances
|
|
$oTmpMask = $this->findPart($oMask->getCurrentInstance($sLevelPartName), $sPartName);
|
|
if($oTmpMask) return $oTmpMask;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* returns latest instance
|
|
* @param String $sPartName
|
|
* @return Mask
|
|
*/
|
|
private function getCurrentInstance($sPartName)
|
|
{
|
|
if(!empty($this->aoInstances[$sPartName]))
|
|
{
|
|
return end($this->aoInstances[$sPartName]);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function setDefaultTagValues() {
|
|
$asTagNames = $this->getTags();
|
|
|
|
//Default translations
|
|
foreach($asTagNames as $sTagName) {
|
|
if(self::isLangTag($sTagName)) $this->setTag($sTagName, $sTagName);
|
|
}
|
|
}
|
|
|
|
public function getTags()
|
|
{
|
|
$asMatches = array('tag'=>array());
|
|
$sSafeTagMark = preg_quote(self::TAG_MARK);
|
|
$sSafeLangMark = preg_quote(self::LANG_PREFIX);
|
|
$sPattern = '/'.$sSafeTagMark.'(?P<tag>('.$sSafeLangMark.'|)[\w\-]+)'.$sSafeTagMark.'/u';
|
|
preg_match_all($sPattern, $this->sMask, $asMatches);
|
|
return array_unique(array_filter($asMatches['tag']));
|
|
}
|
|
|
|
public function setTag($sTagName, $sTagValue, $asTagParams=array())
|
|
{
|
|
$this->asTags[$sTagName] = $sTagValue;
|
|
$this->asTagsParams[$sTagName] = $asTagParams;
|
|
}
|
|
|
|
public function setTags($asTags)
|
|
{
|
|
foreach($asTags as $sTagName=>$sTagValue) $this->setTag($sTagName, $sTagValue);
|
|
}
|
|
|
|
private static function isLangTag($sTag) {
|
|
return (mb_substr($sTag, 0, 5) == self::LANG_PREFIX);
|
|
}
|
|
|
|
private static function isTimeTag($sTag) {
|
|
return (mb_substr($sTag, 0, 5) == self::TIME_PREFIX);
|
|
}
|
|
|
|
public function getMask()
|
|
{
|
|
$sCompletedMask = $this->sMask;
|
|
|
|
//Build Parts
|
|
foreach($this->aoInstances as $sPart=>$aoParts)
|
|
{
|
|
$sTagValue = '';
|
|
foreach($aoParts as $oInstance)
|
|
{
|
|
$sTagValue .= $oInstance->getMask();
|
|
}
|
|
$this->setTag($this->getPartTagPattern($sPart, false), $sTagValue);
|
|
}
|
|
|
|
//Special Tags
|
|
$asTags = $this->asTags;
|
|
foreach($asTags as $sTagName=>&$sTagValue) {
|
|
$sTagActValue = mb_substr($sTagValue, 5);
|
|
|
|
//Translate Tag
|
|
if(!is_null($this->oLang) && self::isLangTag($sTagValue)) $sTagValue = $this->oLang->getTranslation($sTagActValue, $this->asTagsParams[$sTagName]);
|
|
|
|
//Convert Value to Mask Time Zone
|
|
if(self::isTimeTag($sTagValue)) $sTagValue = (new \DateTime('@'.$sTagActValue))->setTimeZone(new \DateTimeZone($this->sTimezone))->format($this->asTagsParams[$sTagName]);;
|
|
}
|
|
|
|
//Replace Tags
|
|
if(!empty($asTags)) {
|
|
$asMarkedTags = $this->addTagMark(array_keys($asTags));
|
|
$sCompletedMask = str_replace($asMarkedTags, $asTags, $sCompletedMask);
|
|
}
|
|
return $sCompletedMask;
|
|
}
|
|
|
|
private function addTagMark($oData)
|
|
{
|
|
return ToolBox::array_map_encapsulate($oData, self::TAG_MARK);
|
|
}
|
|
}
|
|
|
|
?>
|