init
This commit is contained in:
131
inc/main.php
Executable file
131
inc/main.php
Executable file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Main Class
|
||||
* @author franzz
|
||||
* @version 1.0
|
||||
*/
|
||||
class Main extends PhpObject
|
||||
{
|
||||
//Constants
|
||||
//...
|
||||
|
||||
//Objects
|
||||
private $oClassManagement;
|
||||
private $oMySql;
|
||||
private $oTranslator;
|
||||
//...
|
||||
|
||||
//Variables
|
||||
private $sLang;
|
||||
private $asMasks;
|
||||
//...
|
||||
|
||||
/**
|
||||
* Main constructor [to be called from index.php]
|
||||
* @param ClassManagement $oClassManagement
|
||||
* @param string $sLang
|
||||
*/
|
||||
public function __construct($oClassManagement, $sLang='')
|
||||
{
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
$this->oClassManagement = $oClassManagement;
|
||||
|
||||
//Browser <> PHP <> MySql synchronization
|
||||
date_default_timezone_set(Settings::TIMEZONE);
|
||||
ini_set('default_charset', Settings::TEXT_ENC);
|
||||
header('Content-Type: text/html; charset='.Settings::TEXT_ENC);
|
||||
mb_internal_encoding(Settings::TEXT_ENC);
|
||||
mb_http_output(Settings::TEXT_ENC);
|
||||
mb_http_input(Settings::TEXT_ENC);
|
||||
mb_language('uni');
|
||||
mb_regex_encoding(Settings::TEXT_ENC);
|
||||
|
||||
//Load classes
|
||||
$this->oClassManagement->incClass('mask');
|
||||
$this->oClassManagement->incClass('translator');
|
||||
$this->oClassManagement->incClass('mysqlmanager');
|
||||
//...
|
||||
|
||||
//Init objects
|
||||
$this->setLanguage($sLang);
|
||||
$this->setMasks();
|
||||
$this->oTranslator = new Translator($this->getLanguage());
|
||||
$this->oMySql = new MySqlManager(Settings::DB_SERVER, Settings::DB_LOGIN, Settings::DB_PASS, Settings::DB_NAME, self::getSqlOptions() , Settings::DB_ENC);
|
||||
if($this->oMySql->sDbState == MySqlManager::DB_NO_DATA) $this->install();
|
||||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
* DB structure. See MySqlManager::__construct
|
||||
*/
|
||||
private static function getSqlOptions()
|
||||
{
|
||||
return array
|
||||
(
|
||||
'tables' => array
|
||||
(
|
||||
self::USER_TABLE=>array( 'first_name', 'last_name', 'nickname', 'email', 'pass')
|
||||
//...
|
||||
),
|
||||
'types' => array
|
||||
(
|
||||
'first_name'=>"varchar(20) NOT NULL",
|
||||
'last_name'=>"varchar(20) NOT NULL",
|
||||
'nickname'=>"varchar(50) NOT NULL",
|
||||
'email'=>"varchar(100) NOT NULL",
|
||||
'pass'=>"varchar(128) NOT NULL"
|
||||
//...
|
||||
),
|
||||
'constraints' => array
|
||||
(
|
||||
self::USER_TABLE=>"UNIQUE KEY `firstname_lastname_nickname` (`first_name`, `last_name`, `nickname`)"
|
||||
//...
|
||||
),
|
||||
'cascading_delete' => array
|
||||
(
|
||||
self::USER_TABLE=>array(self::DON_TABLE)
|
||||
//...
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private function getLanguage()
|
||||
{
|
||||
return $this->sLang;
|
||||
}
|
||||
|
||||
private function setLanguage($sLang='')
|
||||
{
|
||||
if($sLang!='') $this->sLang = $sLang;
|
||||
else
|
||||
{
|
||||
//$_SERVER['REMOTE_ADDR'] = '193.106.178.41'; //Spain
|
||||
//$_SERVER['REMOTE_ADDR'] = '160.92.167.193'; //France
|
||||
//$_SERVER['REMOTE_ADDR'] = '74.125.230.216'; //US
|
||||
$asIpInfo = json_decode(file_get_contents('http://api.ipinfodb.com/v3/ip-country/?key='.self::LOC_API_KEY.'&format=json&ip='.$_SERVER['REMOTE_ADDR']), true);
|
||||
if($asIpInfo['statusCode'] == 'OK') $this->sLang = $asIpInfo['countryCode'];
|
||||
}
|
||||
}
|
||||
|
||||
private function setMasks()
|
||||
{
|
||||
//List all available masks
|
||||
$asMaskPaths = glob(Mask::getMaskFile('*'));
|
||||
$this->asMasks = array_map('basename', $asMaskPaths, array_fill(1, count($asMaskPaths), Mask::MASK_EXT));
|
||||
}
|
||||
|
||||
private static function jsonExport($asData)
|
||||
{
|
||||
header('Content-type: application/json');
|
||||
//return htmlspecialchars(json_encode($asData), ENT_NOQUOTES);
|
||||
return self::jsonConvert($asData);
|
||||
}
|
||||
|
||||
private static function jsonConvert($asData)
|
||||
{
|
||||
return json_encode($asData);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
231
inc/mask.php
Executable file
231
inc/mask.php
Executable file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mask Reader
|
||||
* @author franzz
|
||||
* @version 1.0
|
||||
*/
|
||||
class Mask extends PhpObject
|
||||
{
|
||||
public $sMaskName;
|
||||
public $sFilePath;
|
||||
private $sMask;
|
||||
private $asTags;
|
||||
private $asPartsSource;
|
||||
private $aoInstances;
|
||||
|
||||
const MASK_FOLDER = 'masks/';
|
||||
const MASK_EXT = '.html';
|
||||
const START_TAG = 'START';
|
||||
const END_TAG = 'END';
|
||||
const TAG_MARK = '[#]';
|
||||
|
||||
public function __construct($sFileName='')
|
||||
{
|
||||
//init
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
$this->sMaskName = '';
|
||||
$this->sFilePath = '';
|
||||
$this->sMask = '';
|
||||
$this->asTags = array();
|
||||
$this->asPartsSource = array();
|
||||
$this->aoInstances = array();
|
||||
$this->sFilePath = '';
|
||||
|
||||
//load file
|
||||
if($sFileName!='')
|
||||
{
|
||||
$this->initFile($sFileName);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
$oInstance->initFileFromString($sPartSource, $sPartName);
|
||||
$oMask->aoInstances[$sPartName][] = $oInstance;
|
||||
}
|
||||
|
||||
public function setInstanceTag($sPartName, $sTagName, $sTagValue)
|
||||
{
|
||||
$oMask = $this->findPart($this, $sPartName);
|
||||
if(!$oMask) $this->addError('No part found : '.$sPartName);
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
private function getCurrentInstance($sPartName)
|
||||
{
|
||||
if(!empty($this->aoInstances[$sPartName]))
|
||||
{
|
||||
return end($this->aoInstances[$sPartName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
$sSafeTagMark = preg_quote(self::TAG_MARK);
|
||||
$sPattern = '/'.$sSafeTagMark.'(?P<tag>\w+)'.$sSafeTagMark.'/u';
|
||||
preg_match_all($sPattern, $this->sMask, $asMatches);
|
||||
return array_unique(array_filter($asMatches['tag']));
|
||||
}
|
||||
|
||||
public function setTag($sTagName, $sTagValue)
|
||||
{
|
||||
$this->asTags[$sTagName] = $sTagValue;
|
||||
}
|
||||
|
||||
public function setTags($asTags)
|
||||
{
|
||||
foreach($asTags as $sTagName=>$sTagValue) $this->setTag($sTagName, $sTagValue);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//replace tags
|
||||
if(!empty($this->asTags))
|
||||
{
|
||||
$asTags = $this->addTagMark(array_keys($this->asTags));
|
||||
$sCompletedMask = str_replace($asTags, $this->asTags, $sCompletedMask);
|
||||
}
|
||||
return $sCompletedMask;
|
||||
}
|
||||
|
||||
private function addTagMark($oData)
|
||||
{
|
||||
return ToolBox::array_map_encapsulate($oData, self::TAG_MARK);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
600
inc/mysqlmanager.php
Executable file
600
inc/mysqlmanager.php
Executable file
@@ -0,0 +1,600 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MySql query manager and generator
|
||||
* @author franzz
|
||||
* @version 1.0
|
||||
*/
|
||||
class MySqlManager extends PhpObject
|
||||
{
|
||||
const DB_NO_CONN = 'ERR_1';
|
||||
const DB_NO_DATA = 'ERR_2';
|
||||
const ID_TAG = 'id_';
|
||||
|
||||
public $sDbState;
|
||||
private $bTrace;
|
||||
private $asOptions;
|
||||
|
||||
/**
|
||||
* SQL connection Handle
|
||||
* @var mysqli
|
||||
*/
|
||||
private $oConnection;
|
||||
private $sDatabase;
|
||||
|
||||
/**
|
||||
* Constructor MySqlManager
|
||||
* @param String $sDbServer
|
||||
* @param String $sLogin
|
||||
* @param String $sPass
|
||||
* @param String $sDatabase
|
||||
* @param Array $asOptions
|
||||
* array( 'tables'=>array('table_name1'=>array('table_field1', 'table_field2', ...), 'table_name2'=>array(...)),
|
||||
* 'types'=>array('field1'=>'field_type1', 'field2'=>'field_type2', ...)
|
||||
* 'constraints'=>array('table_name1'=>'table_contraint1', 'table_name2'=>'table_contraint2', ...),
|
||||
* 'cascading_delete'=>array('table_name1'=>array('linked_table1', 'linked_table2', ...), 'table_name2'=>...))
|
||||
* @param string $sEncoding
|
||||
*/
|
||||
public function __construct($sDbServer, $sLogin, $sPass, $sDatabase, $asOptions, $sEncoding='utf8mb4')
|
||||
{
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
$this->sDatabase = $sDatabase;
|
||||
$this->asOptions = $asOptions;
|
||||
//$this->oConnection = mysql_connect(self::DB_SERVER, self::DB_LOGIN, self::DB_PASS);
|
||||
$this->oConnection = new mysqli($sDbServer, $sLogin, $sPass);
|
||||
$this->syncPhpParams($sEncoding);
|
||||
|
||||
/*
|
||||
$dsn = 'mysql:dbname='.$this->sDatabase.';host='.self::DB_SERVER;
|
||||
try {$dbh = new PDO($dsn, self::DB_LOGIN, self::DB_PASS);}
|
||||
catch (PDOException $e) {$this->addError('Connexion échouée : ' . $e->getMessage());}
|
||||
*/
|
||||
|
||||
$this->setTrace(false);
|
||||
//if(!$this->oConnection)
|
||||
if($this->oConnection->connect_error)
|
||||
{
|
||||
//$this->addError('bug connection');
|
||||
$this->addError('bug connection : '.$this->oConnection->connect_error);
|
||||
$this->sDbState = self::DB_NO_CONN;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if(!mysql_select_db($this->sDatabase, $this->oConnection))
|
||||
if(!$this->oConnection->select_db($this->sDatabase))
|
||||
{
|
||||
$this->addError('bug selecting database. Installing...');
|
||||
$this->sDbState = self::DB_NO_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function syncPhpParams($sEncoding)
|
||||
{
|
||||
//Characters encoding
|
||||
$this->oConnection->set_charset($sEncoding); //SET NAMES
|
||||
|
||||
//Time zone
|
||||
$oNow = new DateTime();
|
||||
$iMins = $oNow->getOffset() / 60;
|
||||
$iSign = ($iMins < 0)?-1:1;
|
||||
$iMins = abs($iMins);
|
||||
$iHours = floor($iMins / 60);
|
||||
$iMins -= $iHours * 60;
|
||||
$sOffset = sprintf('%+d:%02d', $iHours*$iSign, $iMins);
|
||||
$this->setQuery("SET time_zone='{$sOffset}';");
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
parent::__destruct();
|
||||
//mysql_close($this->oConnection);
|
||||
$this->oConnection->close();
|
||||
}
|
||||
|
||||
public function setTrace($bAction)
|
||||
{
|
||||
$this->bTrace = $bAction;
|
||||
}
|
||||
|
||||
public function getTables()
|
||||
{
|
||||
/*
|
||||
$oReflect = new ReflectionClass(__CLASS__);
|
||||
$asConstants = $oReflect->getConstants();
|
||||
$sTableTag = '_TABLE';
|
||||
$asTables = array();
|
||||
foreach($asConstants as $sConstant=>$sConstantValue)
|
||||
{
|
||||
if(mb_strpos($sConstant, $sTableTag)!==false && mb_strpos($sConstant, $sTableTag)==(mb_strlen($sConstant) - mb_strlen($sTableTag)))
|
||||
{
|
||||
$asTables[] = $sConstantValue;
|
||||
}
|
||||
}
|
||||
return $asTables;
|
||||
*/
|
||||
return array_keys($this->asOptions['tables']);
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
//Create Database
|
||||
$this->setQuery("DROP DATABASE IF EXISTS ".$this->sDatabase);
|
||||
$this->setQuery("CREATE DATABASE ".$this->sDatabase." DEFAULT CHARACTER SET ".Settings::DB_ENC." DEFAULT COLLATE ".Settings::DB_ENC."_general_ci");
|
||||
//mysql_select_db($this->sDatabase, $this->oConnection);
|
||||
$this->oConnection->select_db($this->sDatabase);
|
||||
|
||||
//Create tables
|
||||
@array_walk($this->getInstallQueries(), array($this, 'setQuery'));
|
||||
}
|
||||
|
||||
//For debug purposes
|
||||
public function getFullInstallQuery()
|
||||
{
|
||||
$asInstallQueries = $this->getInstallQueries();
|
||||
return str_replace("\n", "<br />", implode(";\n\n", $asInstallQueries))."\n\n<!-- \n".implode(";\n\n", $asInstallQueries)."\n -->";
|
||||
}
|
||||
|
||||
private function getInstallQueries()
|
||||
{
|
||||
$asTables = $this->getTables();
|
||||
$asInstallQueries = array_map(array($this, 'getInstallQuery'), $asTables);
|
||||
$asAlterQueries = $this->getForeignKeyQueries($asTables);
|
||||
return array_merge($asInstallQueries, $asAlterQueries);
|
||||
}
|
||||
|
||||
private function getInstallQuery($sTableName)
|
||||
{
|
||||
$asTableColumns = $this->getTableColumns($sTableName);
|
||||
$sQuery = "\n".$this->implodeAll($asTableColumns, "` ", "\n", "`", ",")."\n".implode(", \n", $this->getTableConstraints($sTableName));
|
||||
return "CREATE TABLE `{$sTableName}` ({$sQuery})";
|
||||
}
|
||||
|
||||
private function getForeignKeyQueries($asTableNames)
|
||||
{
|
||||
$asForeignKeyQueries = array();
|
||||
foreach($asTableNames as $sTableName)
|
||||
{
|
||||
$asTableColumns = array_keys($this->getTablecolumns($sTableName));
|
||||
foreach($asTableColumns as $sColumnName)
|
||||
{
|
||||
if($this->isId($sColumnName) && $sColumnName!=self::getId($sTableName))
|
||||
{
|
||||
$asForeignKeyQueries[] = "ALTER TABLE ".$sTableName." ADD INDEX(`".$sColumnName."`)";
|
||||
$asForeignKeyQueries[] = "ALTER TABLE ".$sTableName." ADD FOREIGN KEY (`".$sColumnName."`) REFERENCES ".self::getTable($sColumnName)."(`".$sColumnName."`)";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $asForeignKeyQueries;
|
||||
}
|
||||
|
||||
private function setQuery($sQuery, $sTypeQuery=__FUNCTION__)
|
||||
{
|
||||
$this->getQuery($sQuery, $sTypeQuery);
|
||||
//return (mysql_affected_rows()!=0);
|
||||
return ($this->oConnection->affected_rows!=0);
|
||||
}
|
||||
|
||||
private function getQuery($sQuery, $sTypeQuery=__FUNCTION__)
|
||||
{
|
||||
$sQuery = str_replace(array("\n", "\t"), array(" ", ""), $sQuery);
|
||||
//$oResult = mysql_query($sQuery, $this->oConnection);
|
||||
|
||||
if($this->bTrace)
|
||||
{
|
||||
$this->setDebug(true);
|
||||
$this->addNotice($sQuery);
|
||||
}
|
||||
|
||||
if(!($oResult = $this->oConnection->query($sQuery)))
|
||||
{
|
||||
$this->addError("\nErreur SQL : \n".str_replace("\t", "", $sQuery)."\n\n".str_replace(array("\t", "\n"), "", $this->oConnection->error));
|
||||
}
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
public function getLastError()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getArrayQuery($sQuery, $bStringOnly=false, $sGroupBy='', $sTypeQuery=__FUNCTION__)
|
||||
{
|
||||
$iIndex = 0;
|
||||
$iColumnCount = 0;
|
||||
$asResult = array();
|
||||
$oResult = $this->getQuery($sQuery, true, $sTypeQuery);
|
||||
if($oResult!==false)
|
||||
{
|
||||
//while($asCurrentRow = mysql_fetch_array($oResult))
|
||||
while($asCurrentRow = $oResult->fetch_array())
|
||||
{
|
||||
if($bStringOnly) $asCurrentRow = $this->arrayKeyFilter($asCurrentRow, 'is_string');
|
||||
|
||||
//Add table reel keys
|
||||
if($sGroupBy!='' && array_key_exists($sGroupBy, $asCurrentRow))
|
||||
{
|
||||
$iRowKey = $asCurrentRow[$sGroupBy];
|
||||
unset($asCurrentRow[$sGroupBy]);
|
||||
}
|
||||
else $iRowKey = $iIndex;
|
||||
|
||||
//For first loop, check table width
|
||||
if($iIndex==0) $iColumnCount = count($asCurrentRow);
|
||||
|
||||
//One column case : collapse a level
|
||||
if($iColumnCount==1) $asCurrentRow = array_shift($asCurrentRow);
|
||||
|
||||
$asResult[$iRowKey] = $asCurrentRow;
|
||||
$iIndex++;
|
||||
}
|
||||
}
|
||||
return $asResult;
|
||||
}
|
||||
|
||||
private function getMaxIncrementedValue($sTable)
|
||||
{
|
||||
return $this->selectValue($sTable, "MAX(".$this->getId($sTable).")");
|
||||
}
|
||||
|
||||
public static function getId($sTableName, $bFull=false)
|
||||
{
|
||||
$sColumnName = self::ID_TAG.self::getText($sTableName);
|
||||
return $bFull?self::getFullColumnName($sTableName, $sColumnName):$sColumnName;
|
||||
}
|
||||
|
||||
public static function getText($sTableName, $bFull=false)
|
||||
{
|
||||
$sColumnName = mb_substr(str_replace('`', '', $sTableName), 0, -1);
|
||||
$sColumnName = mb_substr($sColumnName, -2)=='ie'?mb_substr($sColumnName, 0, -2).'y':$sColumnName;
|
||||
return $bFull?self::getFullColumnName($sTableName, $sColumnName):$sColumnName;
|
||||
}
|
||||
|
||||
public static function getFullColumnName($sTableName, $sColumnName)
|
||||
{
|
||||
return $sTableName.".".$sColumnName;
|
||||
}
|
||||
|
||||
private function isId($sColumnName, $sTableName='')
|
||||
{
|
||||
$asTables = ($sTableName=='')?$this->getTables():array($sTableName);
|
||||
$asTableIds = array_map(array('self', 'getId'), $asTables);
|
||||
return in_array($sColumnName, $asTableIds);
|
||||
}
|
||||
|
||||
private function getTable($sTableId)
|
||||
{
|
||||
$asTables = $this->getTables();
|
||||
$asTableIds = array_map(array('self', 'getId'), $asTables);
|
||||
if(in_array($sTableId, $asTableIds)) return $asTables[array_search($sTableId, $asTableIds)];
|
||||
else
|
||||
{
|
||||
$this->addError('Id '.$sTableId.' présent dans aucune table');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getTablecolumns($sTableName)
|
||||
{
|
||||
if(!array_key_exists($sTableName, $this->asOptions['tables'])) return false;
|
||||
|
||||
$asTableColumns = array(self::getId($sTableName));
|
||||
foreach($this->asOptions['tables'][$sTableName] as $sFieldName) $asTableColumns[] = $sFieldName;
|
||||
$asTableColumns[] = 'led';
|
||||
|
||||
$asTableName = array_fill(0, count($asTableColumns), $sTableName);
|
||||
return array_combine($asTableColumns, array_map(array('self', 'getColumnType'), $asTableColumns, $asTableName));
|
||||
}
|
||||
|
||||
private function getColumnType($sColumnName, $sTableName)
|
||||
{
|
||||
$sColumnType = '';
|
||||
switch($sColumnName)
|
||||
{
|
||||
case array_key_exists($sColumnName, $this->asOptions['types']):
|
||||
$sColumnType = $this->asOptions['types'][$sColumnName];
|
||||
break;
|
||||
case 'led':
|
||||
$sColumnType = "TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP";
|
||||
break;
|
||||
case $this->isId($sColumnName, $sTableName):
|
||||
$sColumnType = "int(10) UNSIGNED auto_increment";
|
||||
break;
|
||||
case $this->isId($sColumnName):
|
||||
$sColumnType = "int(10) UNSIGNED";
|
||||
break;
|
||||
}
|
||||
return $sColumnType;
|
||||
}
|
||||
|
||||
private function getTableConstraints($sTableName)
|
||||
{
|
||||
//Primary key
|
||||
$asTableConstraints = array('PRIMARY' => "PRIMARY KEY (`".self::getId($sTableName)."`)");
|
||||
|
||||
//Foreign keys: applied using ALTER TABLE syntax at the end to prevent scheduling CREATE TABLE queries
|
||||
|
||||
//Other constraints
|
||||
if(array_key_exists($sTableName, $this->asOptions['constraints'])) $asTableConstraints[] = $this->asOptions['constraints'][$sTableName];
|
||||
return $asTableConstraints;
|
||||
}
|
||||
|
||||
private function addQuotes($oData)
|
||||
{
|
||||
//TODO remake
|
||||
$asTrustedFunc = array('CURDATE()', 'NOW()');
|
||||
$sChar = "'";
|
||||
if(is_array($oData))
|
||||
{
|
||||
$asChar = array_fill(1, count($oData), $sChar);
|
||||
return array_combine(array_keys($oData), array_map(array($this, 'addQuotes'), $oData, $asChar));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(in_array($oData, $asTrustedFunc)) return $oData;
|
||||
else return $sChar.$oData.$sChar;
|
||||
}
|
||||
}
|
||||
|
||||
private function getLastId()
|
||||
{
|
||||
return $this->oConnection->insert_id;
|
||||
}
|
||||
|
||||
public function insertRow($sTableName, $asData)
|
||||
{
|
||||
$this->cleanSql($sTableName);
|
||||
$this->cleanSql($asData);
|
||||
|
||||
$asQueryValues = $this->addQuotes($asData);
|
||||
$sQuery = "INSERT INTO ".$sTableName." (`".implode("`, `", array_keys($asQueryValues))."`) VALUES (".implode(", ", $asQueryValues).")";
|
||||
return $this->setQuery($sQuery)?$this->getLastId():0;
|
||||
}
|
||||
|
||||
public function updateRow($sTableName, $asConstraints, $asData)
|
||||
{
|
||||
return $this->updateRows($sTableName, $asConstraints, $asData, 1);
|
||||
}
|
||||
|
||||
public function updateRows($sTableName, $asConstraints, $asData, $iLimit=0)
|
||||
{
|
||||
if(!is_array($asConstraints))
|
||||
{
|
||||
$asConstraints = array($this->getId($sTableName)=>$asConstraints);
|
||||
}
|
||||
|
||||
$this->cleanSql($sTableName);
|
||||
$this->cleanSql($iTableId);
|
||||
$this->cleanSql($asData);
|
||||
$this->cleanSql($asConstraints);
|
||||
$asQueryValues = $this->addQuotes($asData);
|
||||
$asConstraintsValues = $this->addQuotes($asConstraints);
|
||||
$this->addColumnSelectors($asQueryValues);
|
||||
$this->addColumnSelectors($asConstraintsValues);
|
||||
|
||||
$sLimit = $iLimit>0?" LIMIT $iLimit":"";
|
||||
$sQuery = "UPDATE {$sTableName} ".
|
||||
"SET ".$this->implodeAll($asQueryValues, " = ", ", ")." ".
|
||||
"WHERE ".$this->implodeAll($asConstraintsValues, " = ", " AND ").$sLimit;
|
||||
|
||||
$iResult = false;
|
||||
if($this->setQuery($sQuery))
|
||||
{
|
||||
$iResult = ($iLimit==1)?$this->selectValue($sTableName, $this->getId($sTableName), $asConstraints):true;
|
||||
}
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
public function insertUpdateRow($sTableName, $asData, $asKeys=array(), $bUpdate=true)
|
||||
{
|
||||
$sTableIdName = self::getId($sTableName);
|
||||
|
||||
//check for data in the db
|
||||
if($asKeys==array())
|
||||
{
|
||||
$asKeys[] = $sTableIdName;
|
||||
}
|
||||
$asValues = array_intersect_key($asData, array_flip($asKeys));
|
||||
$iTableId = $this->selectValue($sTableName, $sTableIdName, $asValues);
|
||||
|
||||
//insert
|
||||
if(!$iTableId)
|
||||
{
|
||||
$iTableId = $this->insertRow($sTableName, $asData);
|
||||
}
|
||||
//Update
|
||||
elseif($bUpdate)
|
||||
{
|
||||
if(array_key_exists($sTableIdName, $asData))
|
||||
{
|
||||
unset($asData[$sTableIdName]);
|
||||
}
|
||||
$iTableId = $this->updateRow($sTableName, $iTableId, $asData);
|
||||
}
|
||||
return $iTableId;
|
||||
}
|
||||
|
||||
public function selectInsert($sTableName, $asData, $asKeys=array())
|
||||
{
|
||||
return $this->insertUpdateRow($sTableName, $asData, $asKeys, false);
|
||||
}
|
||||
|
||||
public function deleteRow($sTableName, $iTableId)
|
||||
{
|
||||
$this->cleanSql($sTableName);
|
||||
$this->cleanSql($iTableId);
|
||||
|
||||
//linked tables
|
||||
switch($sTableName)
|
||||
{
|
||||
case array_key_exists($sTableName, $this->asOptions['cascading_delete']) :
|
||||
$asTables = array_filter(is_array($sTableName)?$sTableName:array($sTableName) + $this->asOptions['cascading_delete'][$sTableName]);
|
||||
break;
|
||||
case is_string($sTableName) :
|
||||
$asTables = array($sTableName);
|
||||
break;
|
||||
case is_array($sTableName):
|
||||
$asTables = $sTableName;
|
||||
break;
|
||||
default:
|
||||
$asTables = array();
|
||||
}
|
||||
foreach($asTables as $sTable)
|
||||
{
|
||||
$this->setQuery("DELETE FROM ".$sTable." WHERE ".$this->getId($sTableName)." = ".$iTableId);
|
||||
}
|
||||
}
|
||||
|
||||
public function selectRows($asInfo, $bStringOnly=true, $sGroupBy='')
|
||||
{
|
||||
$asAttributes = array('select'=>"SELECT", 'from'=>"FROM", 'join'=>"LEFT JOIN", 'joinOn'=>"LEFT JOIN", 'constraint'=>"WHERE", 'groupBy'=>"GROUP BY", 'orderBy'=>"ORDER BY", 'limit'=>'LIMIT');
|
||||
$asRowSeparators = array('select'=>", ", 'from'=>"", 'join'=>" LEFT JOIN ", 'joinOn'=>" LEFT JOIN ", 'constraint'=>" AND ", 'groupBy'=>", ", 'orderBy'=>", ", 'limit'=>"");
|
||||
$asOperators = array('constraint'=>" = ", 'orderBy'=>" ", 'join'=>" USING(", 'joinOn'=>" ON ");
|
||||
$asEndOfStatement = array('constraint'=>"", 'orderBy'=>"", 'join'=>")", 'joinOn'=>"");
|
||||
|
||||
//$sQuery = "/* ".str_replace(array("\n", "\t"), '', print_r($asInfo, true))." */";
|
||||
$sQuery = "";
|
||||
foreach($asAttributes as $sStatement => $sKeyWord)
|
||||
{
|
||||
$asSelection = array_key_exists($sStatement, $asInfo)?$asInfo[$sStatement]:array();
|
||||
if(!is_array($asSelection))
|
||||
{
|
||||
$asSelection = array($asSelection);
|
||||
}
|
||||
|
||||
//if provided values
|
||||
if(!empty($asSelection))
|
||||
{
|
||||
$this->cleanSql($asSelection);
|
||||
|
||||
if($sStatement=='constraint' && !array_key_exists('constVar', $asInfo))
|
||||
{
|
||||
$asSelection = $this->addQuotes($asSelection);
|
||||
}
|
||||
$this->addColumnSelectors($asSelection);
|
||||
|
||||
$sQuery .= " ".$sKeyWord." ";
|
||||
|
||||
//in case of double value input
|
||||
if(array_key_exists($sStatement, $asOperators))
|
||||
{
|
||||
if($sStatement=='constraint' && array_key_exists('constOpe', $asInfo))
|
||||
{
|
||||
$asOperators[$sStatement] = $asInfo['constOpe'];
|
||||
}
|
||||
$sQuery .= $this->implodeAll($asSelection, $asOperators[$sStatement], $asRowSeparators[$sStatement], "", $asEndOfStatement[$sStatement]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sQuery .= implode($asRowSeparators[$sStatement], $asSelection);
|
||||
}
|
||||
}
|
||||
//default value for select
|
||||
elseif($sStatement=='select')
|
||||
{
|
||||
$sQuery .= " ".$sKeyWord." * ";
|
||||
}
|
||||
}
|
||||
return $this->getArrayQuery($sQuery, $bStringOnly, $sGroupBy);
|
||||
}
|
||||
|
||||
private function addColumnSelectors(&$asSelection)
|
||||
{
|
||||
//TODO get rid of this
|
||||
$sSqlWord = 'option';
|
||||
$sKey = array_search($sSqlWord, $asSelection);
|
||||
if($sKey!==false)
|
||||
{
|
||||
$asSelection[$sKey] = "`".$asSelection[$sKey]."`";
|
||||
}
|
||||
elseif(array_key_exists($sSqlWord, $asSelection))
|
||||
{
|
||||
$asSelection["`".$sSqlWord."`"] = $asSelection[$sSqlWord];
|
||||
unset($asSelection[$sSqlWord]);
|
||||
}
|
||||
}
|
||||
|
||||
public function selectRow($sTableName, $asConstraints=array(), $sColumnName='*')
|
||||
{
|
||||
if(!is_array($asConstraints))
|
||||
{
|
||||
$asConstraints = array($this->getId($sTableName)=>$asConstraints);
|
||||
}
|
||||
$asResult = $this->selectRows(array('select'=>$sColumnName, 'from'=>$sTableName, 'constraint'=>$asConstraints));
|
||||
$iCountNb = count($asResult);
|
||||
switch($iCountNb)
|
||||
{
|
||||
case 0 :
|
||||
return false;
|
||||
case $iCountNb > 1 :
|
||||
$this->addError('Trop de résultats pour un selectRow() : '.$iCountNb.' lignes. Table: '.$sTableName.', contrainte: '.self::implodeAll($asConstraints, '=', ' ').', colonne: '.$sColumnName);
|
||||
break;
|
||||
}
|
||||
return array_shift($asResult);
|
||||
}
|
||||
|
||||
public function selectValue($sTableName, $sColumnName, $oConstraints=array())
|
||||
{
|
||||
if(!is_array($oConstraints))
|
||||
{
|
||||
$oConstraints = array($this->getId($sTableName)=>$oConstraints);
|
||||
}
|
||||
return $this->selectRow($sTableName, $oConstraints, $sColumnName);
|
||||
}
|
||||
|
||||
public function pingValue($sTableName, $oConstraints)
|
||||
{
|
||||
return $this->selectValue($sTableName, 'COUNT(1)', $oConstraints);
|
||||
}
|
||||
|
||||
public function cleanSql(&$oData)
|
||||
{
|
||||
//self::cleanData($oData, 'mysql_real_escape_string');
|
||||
//$oData = self::cleanData($oData, 'mysql_real_escape_string');
|
||||
$this->cleanData($oData);
|
||||
$oData = $this->cleanData($oData);
|
||||
}
|
||||
|
||||
public static function implodeAll($asText, $asKeyValueSeparator='', $sRowSeparator='', $sKeyPre='', $sValuePost=false)
|
||||
{
|
||||
if($sValuePost===false)
|
||||
{
|
||||
$sValuePost = $sKeyPre;
|
||||
}
|
||||
$asCombinedText = array();
|
||||
|
||||
//if unique value for key value separator
|
||||
if(!is_array($asKeyValueSeparator) && !empty($asText))
|
||||
{
|
||||
$asKeyValueSeparator = array_combine(array_keys($asText), array_fill(0, count($asText), $asKeyValueSeparator));
|
||||
}
|
||||
|
||||
foreach($asText as $sKey=>$sValue)
|
||||
{
|
||||
$asCombinedText[] = $sKeyPre.$sKey.$asKeyValueSeparator[$sKey].(is_array($sValue)?implode($sValue):$sValue).$sValuePost;
|
||||
}
|
||||
return implode($sRowSeparator, $asCombinedText);
|
||||
}
|
||||
|
||||
public static function arrayKeyFilter($asArray, $sCallBack)
|
||||
{
|
||||
$asValidKeys = array_flip(array_filter(array_keys($asArray), $sCallBack));
|
||||
return array_intersect_key($asArray, $asValidKeys);
|
||||
}
|
||||
|
||||
public function cleanData($oData)
|
||||
{
|
||||
if(!is_array($oData))
|
||||
{
|
||||
return $this->oConnection->real_escape_string($oData);
|
||||
}
|
||||
elseif(count($oData)>0)
|
||||
{
|
||||
$asKeys = array_map(array($this, 'cleanData'), array_keys($oData));
|
||||
$asValues = array_map(array($this, 'cleanData'), $oData);
|
||||
return array_combine($asKeys, $asValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
169
inc/rss.php
Executable file
169
inc/rss.php
Executable file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RSS Feed Class
|
||||
* @author franzz
|
||||
* @version 1.1
|
||||
*
|
||||
* Input:
|
||||
* - $asDesc: Array. Description of the feed: fields 'title', 'link' (optional), 'copyright', 'description', 'language', 'webmaster_mail'
|
||||
* - $asItems: Array. Feed item data: fields 'title', 'description', 'author', 'link', 'pub_date', 'guid'
|
||||
*/
|
||||
class Feed extends PhpObject {
|
||||
|
||||
private $asDesc;
|
||||
private $asItems;
|
||||
|
||||
public function __construct($asDesc, $asItems=array())
|
||||
{
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
if(!array_key_exists('link', $asDesc))
|
||||
{
|
||||
$asDesc['link'] = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'].'/rss';
|
||||
}
|
||||
$this->asDesc = $asDesc;
|
||||
array_walk($asItems, array($this, 'addItem'));
|
||||
}
|
||||
|
||||
public function addItem($asItem)
|
||||
{
|
||||
$this->asItems[] = $asItem;
|
||||
return count($this->asItems) - 1;
|
||||
}
|
||||
|
||||
public function removeItem($iItemId)
|
||||
{
|
||||
$bExist = array_key_exists($iItemId, $this->asItems);
|
||||
if($bExist) unset($this->asItems[$iItemId]);
|
||||
return $bExist;
|
||||
}
|
||||
|
||||
private function getGlobalPubDate()
|
||||
{
|
||||
$iGlobalPubDate = 0;
|
||||
foreach($this->asItems as $asItem)
|
||||
{
|
||||
$iItemPubDate = strtotime($asItem['pub_date']);
|
||||
if($iItemPubDate>$iGlobalPubDate)
|
||||
{
|
||||
$iGlobalPubDate = $iItemPubDate;
|
||||
}
|
||||
}
|
||||
return self::cleanRss(self::getDate($iGlobalPubDate));
|
||||
}
|
||||
|
||||
public function getFeed()
|
||||
{
|
||||
|
||||
//feed header
|
||||
$sRssFeedHeader = self::getHtml($this->asDesc['title'], 'title');
|
||||
$sRssFeedHeader .= self::getHtml($this->asDesc['link'], 'link');
|
||||
$sRssFeedHeader .= self::getHtml($this->asDesc['copyright'], 'copyright');
|
||||
$sRssFeedHeader .= self::getHtml($this->asDesc['description'], 'description');
|
||||
$sRssFeedHeader .= self::getHtml('', 'atom:link', '', '', array('href'=>$this->asDesc['link'], 'rel'=>'self', 'type'=>'application/atom+xml'), true);
|
||||
$sRssFeedHeader .= self::getHtml($this->asDesc['language'], 'language');
|
||||
$sRssFeedHeader .= self::getHtml($this->getGlobalPubDate(), 'pubDate');
|
||||
$sRssFeedHeader .= self::getHtml('Lutran.fr RSS Feed Generator', 'generator');
|
||||
$sRssFeedHeader .= self::getHtml($this->asDesc['webmaster_mail'].' (Webmaster)', 'webMaster');
|
||||
|
||||
//feed items
|
||||
$asSortedItems = $this->rSortTimeMatrix($this->asItems, 'pub_date');
|
||||
$sItems = implode("\n", array_map(array($this, 'buildItem'), $asSortedItems));
|
||||
|
||||
//Global Feed
|
||||
$sFeed = '<?xml version="1.0" encoding="'.Settings::TEXT_ENC.'" ?>';
|
||||
$sFeed .= self::getHtml(self::getHtml($sRssFeedHeader.$sItems, 'channel'), 'rss', '', '', array('version'=>'2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom'));
|
||||
|
||||
return $sFeed;
|
||||
}
|
||||
|
||||
private static function getDate($sDate)
|
||||
{
|
||||
if(!is_numeric($sDate))
|
||||
{
|
||||
$sDate = strtotime($sDate);
|
||||
}
|
||||
return date('r', $sDate);
|
||||
}
|
||||
|
||||
private function buildItem($asItem)
|
||||
{
|
||||
$sRssItem = self::getHtml(self::cleanRss($asItem['title']), 'title');
|
||||
$sRssItem .= self::getHtml(self::cleanRss($asItem['author']), 'author');
|
||||
$sRssItem .= self::getHtml($asItem['link'], 'link');
|
||||
$sRssItem .= self::getHtml($asItem['category'], 'category');
|
||||
$sRssItem .= self::getHtml(self::cleanRss($asItem['description'].'.'), 'description');
|
||||
$sRssItem .= self::getHtml(self::getDate($asItem['pub_date']), 'pubDate');
|
||||
$sRssItem .= self::getHtml($asItem['guid'], 'guid', '', '', array('isPermaLink'=>'true'));
|
||||
return self::getHtml($sRssItem, 'item');
|
||||
}
|
||||
|
||||
private static function getHtml($oText, $sTag, $sClass='', $sStyle='', $asExtraAttr=array(), $bAutoClose=false, $sInter='')
|
||||
{
|
||||
$sHtmlAttr = '';
|
||||
if($sClass!='')
|
||||
{
|
||||
$asExtraAttr['class'] = $sClass;
|
||||
}
|
||||
if($sStyle!='')
|
||||
{
|
||||
$asExtraAttr['style'] = $sStyle;
|
||||
}
|
||||
foreach($asExtraAttr as $sAttrName=>$sAttrValue)
|
||||
{
|
||||
$sHtmlAttr .= ' '.$sAttrName.'="'.$sAttrValue.'"';
|
||||
}
|
||||
if($bAutoClose)
|
||||
{
|
||||
$sHtml = self::encapsulate('', "\n".'<'.$sTag.$sHtmlAttr, ' />');
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml = self::encapsulate($oText, "\n".'<'.$sTag.$sHtmlAttr.'>', '</'.$sTag.'>', $sInter);
|
||||
}
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
private static function cleanRss($oText)
|
||||
{
|
||||
$asForbiddenChars = array('&', '<', '>', '"', "'");
|
||||
$asReplacementCode = array('&', '<', '>', '"', ''');
|
||||
if(!is_array($oText))
|
||||
{
|
||||
return str_replace($asForbiddenChars, $asReplacementCode, $oText);
|
||||
}
|
||||
elseif(count($oText)>0)
|
||||
{
|
||||
$oTextKeys = array_map(array($this, 'cleanRss'), array_keys($oText));
|
||||
$oTextValues = array_map(array($this, 'cleanRss'), array_values($oText));
|
||||
return array_combine($oTextKeys, $oTextValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $oText;
|
||||
}
|
||||
}
|
||||
|
||||
private static function encapsulate($oText, $sPre='', $sPost=false, $sInter='')
|
||||
{
|
||||
if($sPost===false)
|
||||
{
|
||||
$sPost = $sPre;
|
||||
}
|
||||
if(is_array($oText))
|
||||
{
|
||||
$oText = implode($sPost.$sInter.$sPre, $oText);
|
||||
}
|
||||
return $sPre.$oText.$sPost;
|
||||
}
|
||||
|
||||
private static function rSortTimeMatrix($asMatrix, $sTimeCol)
|
||||
{
|
||||
$asResult = array();
|
||||
foreach($asMatrix as $iRowId=>$asLine) $asKeys[$iRowId] = strtotime($asLine[$sTimeCol]);
|
||||
arsort($asKeys);
|
||||
foreach($asKeys as $iRowId=>$iTimeStamp) $asResult[$iRowId] = $asMatrix[$iRowId];
|
||||
return $asResult;
|
||||
}
|
||||
}
|
||||
?>
|
||||
235
inc/toolbox.php
Executable file
235
inc/toolbox.php
Executable file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ToolBox - Only static functions missing from php librairy
|
||||
* @author franzz
|
||||
* @version 1.1
|
||||
*/
|
||||
class ToolBox
|
||||
{
|
||||
const MAIL_SUCCESS = 2;
|
||||
|
||||
public static function cleanPost(&$asData)
|
||||
{
|
||||
//get rid of magic quotes
|
||||
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
|
||||
{
|
||||
$asData = self::cleanData($asData, 'stripslashes');
|
||||
}
|
||||
}
|
||||
|
||||
public static function cleanData($oData, $sCleaningFunc)
|
||||
{
|
||||
if(!is_array($oData))
|
||||
{
|
||||
return call_user_func($sCleaningFunc, $oData);
|
||||
}
|
||||
elseif(count($oData)>0)
|
||||
{
|
||||
$asCleaningFunc = array_fill(1, count($oData), $sCleaningFunc);
|
||||
$asKeys = array_map(array('self', 'cleanData'), array_keys($oData), $asCleaningFunc);
|
||||
$asValues = array_map(array('self', 'cleanData'), $oData, $asCleaningFunc);
|
||||
return array_combine($asKeys, $asValues);
|
||||
}
|
||||
}
|
||||
|
||||
public static function fixGlobalVars($argv)
|
||||
{
|
||||
//Add CLI arguments
|
||||
if(defined('STDIN')) mb_parse_str(implode('&', array_slice($argv, 1)), $_GET);
|
||||
|
||||
//Add Server Name
|
||||
$sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD'];
|
||||
$sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME']));
|
||||
$_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':'');
|
||||
}
|
||||
|
||||
public static function array_map_encapsulate($oData, $sChar)
|
||||
{
|
||||
if(is_array($oData))
|
||||
{
|
||||
$asChar = array_fill(1, count($oData), $sChar);
|
||||
return array_combine(array_keys($oData), array_map(array('self', 'array_map_encapsulate'), $oData, $asChar));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $sChar.$oData.$sChar;
|
||||
}
|
||||
}
|
||||
|
||||
public static function capitalizeWords($acText, $sCharList = '')
|
||||
{
|
||||
//Use ucwords if no delimiters are given
|
||||
if($sCharList=='')
|
||||
{
|
||||
return Toolbox::mb_ucwords($acText);
|
||||
}
|
||||
|
||||
// Go through all characters
|
||||
$capitalizeNext = true;
|
||||
$max = mb_strlen($acText);
|
||||
for ($i = 0; $i < $max; $i++)
|
||||
{
|
||||
if(mb_strpos($sCharList, $acText[$i]) !== false)
|
||||
{
|
||||
$capitalizeNext = true;
|
||||
}
|
||||
elseif($capitalizeNext)
|
||||
{
|
||||
$capitalizeNext = false;
|
||||
$acText[$i] = mb_strtoupper($acText[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return $acText;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param String $sFromName
|
||||
* @param String $sSubject
|
||||
* @param String $sMessage
|
||||
* @param String $sTo
|
||||
* @param Array $asCc array(name => email)
|
||||
* @param Boolean $bSelfMail
|
||||
* @return mixed
|
||||
*/
|
||||
public function sendMail($sFromName, $sSubject, $sMessage, $sTo, $asCc=array(), $bSelfMail=true)
|
||||
{
|
||||
$asForm = array('api_key'=>Settings::MAIL_API_KEY,
|
||||
'app'=>'Wedding',
|
||||
'from_name'=>$sFromName,
|
||||
'subject'=>$sSubject,
|
||||
'msg'=>$sMessage,
|
||||
'to_email'=>$sTo,
|
||||
'cc_email'=>self::jsonConvert($asCc),
|
||||
'self'=>$bSelfMail);
|
||||
|
||||
$oCurl = curl_init();
|
||||
curl_setopt($oCurl, CURLOPT_URL, Settings::MAIL_SCRIPT);
|
||||
curl_setopt($oCurl, CURLOPT_POST, true);
|
||||
curl_setopt($oCurl, CURLOPT_HEADER, false);
|
||||
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($oCurl, CURLOPT_POSTFIELDS, $asForm);
|
||||
$iResult = curl_exec($oCurl);
|
||||
curl_close($oCurl);
|
||||
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
public static function jsonExport($asData)
|
||||
{
|
||||
header('Content-type: application/json');
|
||||
//return htmlspecialchars(json_encode($asData), ENT_NOQUOTES);
|
||||
return self::jsonConvert($asData);
|
||||
}
|
||||
|
||||
public static function jsonConvert($asData)
|
||||
{
|
||||
return json_encode($asData);
|
||||
}
|
||||
|
||||
public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight, $sOutPath='', $bDeleteIn=false, $asImageExts=array('jpg', 'jpeg', 'gif', 'png'))
|
||||
{
|
||||
$asResult = array('error'=>'');
|
||||
|
||||
//Look up the extension to choose the image creator
|
||||
//TODO use MIME types
|
||||
$sInInfo = pathinfo($sInPath);
|
||||
$sInName = mb_strtolower($sInInfo['basename']);
|
||||
$sImageExt = mb_strtolower($sInInfo['extension']);
|
||||
$sImageExt = ($sImageExt=='jpg')?'jpeg':$sImageExt;
|
||||
|
||||
//New Destination folder
|
||||
if($sOutPath=='') $sOutPath = $sInPath;
|
||||
elseif(mb_substr($sOutPath, -1)=='/') $sOutPath .= $sInName;
|
||||
|
||||
//New sizes
|
||||
if(in_array($sImageExt, $asImageExts))
|
||||
{
|
||||
list($iWidth, $iHeight) = getimagesize($sInPath);
|
||||
if($iWidth > $iMaxWidth || $iHeight > $iMaxHeight)
|
||||
{
|
||||
$dResizeDeltaWidth = $iWidth - $iMaxWidth;
|
||||
$dResizeDeltaHeight = $iHeight - $iMaxHeight;
|
||||
if($dResizeDeltaWidth > $dResizeDeltaHeight)
|
||||
{
|
||||
$iResizedWidth = $iMaxWidth;
|
||||
$iResizedHeight = ($iResizedWidth / $iWidth) * $iHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
$iResizedHeight = $iMaxHeight;
|
||||
$iResizedWidth = ($iResizedHeight / $iHeight) * $iWidth;
|
||||
}
|
||||
|
||||
//create image from source
|
||||
$oSource = call_user_func('imagecreatefrom'.$sImageExt, $sInPath);
|
||||
|
||||
//Resize
|
||||
$oThumb = imagecreatetruecolor($iResizedWidth, $iResizedHeight);
|
||||
imagecopyresized($oThumb, $oSource, 0, 0, 0, 0, $iResizedWidth, $iResizedHeight, $iWidth, $iHeight);
|
||||
|
||||
//Save
|
||||
if(file_exists($sOutPath)) unlink($sOutPath);
|
||||
if(!call_user_func_array('image'.$sImageExt, array($oThumb, $sOutPath)))
|
||||
{
|
||||
$asResult['error'] = 'Unable to create thumbnail : '.$sOutPath;
|
||||
}
|
||||
}
|
||||
elseif($sInPath != $sOutPath)
|
||||
{
|
||||
$iResizedWidth = $iWidth;
|
||||
$iResizedHeight = $iHeight;
|
||||
if(!copy($sInPath, $sOutPath)) $asResult['error'] = 'Copy failed from '.$sInPath.' to '.$sOutPath;
|
||||
}
|
||||
$asResult['width'] = $iResizedWidth;
|
||||
$asResult['height'] = $iResizedHeight;
|
||||
$asResult['out'] = $sOutPath;
|
||||
}
|
||||
else $asResult['error'] = 'Wrong file type';
|
||||
|
||||
if($bDeleteIn && $asResult['error']=='' && $sInPath != $sOutPath) unlink($sInPath);
|
||||
|
||||
return $asResult;
|
||||
}
|
||||
|
||||
public static function utf8_compliant($sText)
|
||||
{
|
||||
if(strlen($sText) == 0) return true;
|
||||
return (preg_match('/^.{1}/us', $sText, $ar) == 1);
|
||||
}
|
||||
|
||||
public static function mb_ucwords($sText)
|
||||
{
|
||||
return mb_convert_case($sText, MB_CASE_TITLE, "UTF-8");
|
||||
}
|
||||
|
||||
public static function file_get_contents_utf8($oFile)
|
||||
{
|
||||
$sContent = file_get_contents($oFile);
|
||||
return mb_convert_encoding($sContent, 'UTF-8', mb_detect_encoding($sContent, 'UTF-8, ISO-8859-1', true));
|
||||
}
|
||||
|
||||
public static function rgbToHex($R, $G, $B)
|
||||
{
|
||||
$R = dechex($R);
|
||||
if(strlen($R)<2) $R='0'.$R;
|
||||
|
||||
$G = dechex($G);
|
||||
if(strlen($G)<2) $G='0'.$G;
|
||||
|
||||
$B = dechex($B);
|
||||
if(strlen($B)<2) $B='0'.$B;
|
||||
|
||||
return $R.$G.$B;
|
||||
}
|
||||
|
||||
public static function setCookie($sCookieName, $sCookieValue, $iDays)
|
||||
{
|
||||
$iTimeLimit = time()+60*60*24*$iDays;
|
||||
setcookie($sCookieName, $sCookieValue, $iTimeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
117
inc/translator.php
Executable file
117
inc/translator.php
Executable file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Translator Class
|
||||
* @author franzz
|
||||
* @version 1.0
|
||||
*/
|
||||
class Translator extends PhpObject
|
||||
{
|
||||
private $sLang;
|
||||
private $asLanguages;
|
||||
private $asTranslations; // [lang][key_word] = translation
|
||||
|
||||
const LANG_FOLDER = 'languages/';
|
||||
const LANG_EXT = '.lang';
|
||||
const LANG_SEP = '=';
|
||||
const DEFAULT_LANG = 'FR';
|
||||
|
||||
public function __construct($sLang='')
|
||||
{
|
||||
parent::__construct(__CLASS__, Settings::DEBUG);
|
||||
$this->asLanguages = array();
|
||||
$this->asTranslations = array();
|
||||
$this->loadLanguages();
|
||||
$this->setLanguage($sLang);
|
||||
}
|
||||
|
||||
public function setLanguage($sLang)
|
||||
{
|
||||
$this->sLang = in_array($sLang, $this->asLanguages)?$sLang:self::DEFAULT_LANG;
|
||||
}
|
||||
|
||||
public function getTranslation($sTransKey, $sLang='')
|
||||
{
|
||||
$sTransText = false;
|
||||
|
||||
//Select language
|
||||
if($sLang=='')
|
||||
{
|
||||
$sLang = $this->sLang;
|
||||
}
|
||||
|
||||
//Look up in the selected language dictionary
|
||||
if(in_array($sLang, $this->asLanguages) && array_key_exists($sTransKey, $this->asTranslations[$sLang]))
|
||||
{
|
||||
$sTransText = $this->asTranslations[$sLang][$sTransKey];
|
||||
}
|
||||
//Look up in the default language dictionary
|
||||
elseif(array_key_exists($sTransKey, $this->asTranslations[self::DEFAULT_LANG]))
|
||||
{
|
||||
$this->addWarning('Missing translation in "'.$sLang.'" for the key "'.$sTransKey.'", falling back to "'.self::DEFAULT_LANG.'"');
|
||||
$sTransText = $this->asTranslations[self::DEFAULT_LANG][$sTransKey];
|
||||
}
|
||||
else $this->addWarning('Missing translation in "'.$sLang.'" for the key "'.$sTransKey.'"');
|
||||
|
||||
return $sTransText;
|
||||
}
|
||||
|
||||
public function getHashToPage($asMenuPages)
|
||||
{
|
||||
$asHashToPage = array();
|
||||
foreach($asMenuPages as $sHash)
|
||||
{
|
||||
foreach($this->asLanguages as $sLang)
|
||||
{
|
||||
$asHashToPage[$this->getTranslation('menu_'.$sHash.'_key', $sLang)] = $sHash;
|
||||
}
|
||||
}
|
||||
return $asHashToPage;
|
||||
}
|
||||
|
||||
public function getPageToHash($asMenuPages)
|
||||
{
|
||||
$asPageToHash = array();
|
||||
foreach($asMenuPages as $sHash)
|
||||
{
|
||||
$asPageToHash[$sHash] = $this->getTranslation('menu_'.$sHash.'_key');
|
||||
}
|
||||
return $asPageToHash;
|
||||
}
|
||||
|
||||
private function loadLanguages()
|
||||
{
|
||||
//List all available languages
|
||||
$asLangPaths = glob(self::getLangPath('*'));
|
||||
$this->asLanguages = array_map('basename', $asLangPaths, array_fill(1, count($asLangPaths), self::LANG_EXT));
|
||||
|
||||
//Load languages
|
||||
array_walk($this->asLanguages, array($this, 'loadLanguageFile'));
|
||||
}
|
||||
|
||||
private function loadLanguageFile($sLang)
|
||||
{
|
||||
if(!in_array($sLang, $this->asTranslations))
|
||||
{
|
||||
$sData = file_get_contents(self::getLangPath($sLang));
|
||||
$asData = explode("\n", $sData);
|
||||
foreach($asData as $sTranslation)
|
||||
{
|
||||
$iSepPos = stripos($sTranslation, self::LANG_SEP);
|
||||
if($iSepPos!==false)
|
||||
{
|
||||
$sTransKey = trim(substr($sTranslation, 0, $iSepPos));
|
||||
$sTransText = /*htmlspecialchars(*/trim(substr($sTranslation, $iSepPos+1))/*, ENT_QUOTES)*/; //TODO when all entities have been removed
|
||||
$this->asTranslations[$sLang][$sTransKey] = $sTransText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function getLangPath($sLang)
|
||||
{
|
||||
return self::LANG_FOLDER.$sLang.self::LANG_EXT;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user