v1.0.0 RC 1

This commit is contained in:
2014-06-14 18:04:27 +02:00
parent 16387ca7d1
commit 8da730253d
109 changed files with 10834 additions and 8132 deletions

25
inc/auth.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
/**
* Auth Class
* TODO move all auth related topics here
* @author lutranf
*
*/
class Auth
{
const ALGO = PASSWORD_DEFAULT;
const COST = 12;
public static function HashPassword($sPass)
{
return password_hash($sPass, self::ALGO, array('cost'=>self::COST));
}
public static function CheckPassword($sPass, $sHash)
{
return password_verify($sPass, $sHash);
}
}
?>

2507
inc/databap.php Normal file

File diff suppressed because it is too large Load Diff

158
inc/fileuploader.php Normal file
View File

@@ -0,0 +1,158 @@
<?php
class fileUploader
{
const GET_NAME = 'qqfile';
private $asAllowedExtensions;
private $iSizeLimit;
private $sFolderPath;
function __construct($sFolderPath, $asAllowedExtensions = array()/*, $sizeLimit = 10485760*/)
{
$this->sFolderPath = $sFolderPath;
$this->asAllowedExtensions = array_map("mb_strtolower", $asAllowedExtensions);
//$this->iSizeLimit = $sizeLimit;
//$this->checkServerSettings();
$this->iSizeLimit = Databap::getMaxSize();
/*
if(isset($_GET[self::GET_NAME]))
{
//$this->file = new qqUploadedFileXhr();
}
elseif(isset($_FILES[self::GET_NAME])) {
$this->file = new qqUploadedFileForm();
}
else
{
$this->file = false;
}
*/
}
/*
private function checkServerSettings()
{
$postSize = $this->toBytes(ini_get('post_max_size'));
$uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
if($postSize < $this->iSizeLimit || $uploadSize < $this->iSizeLimit){
$size = max(1, $this->iSizeLimit / 1024 / 1024) . 'M';
die("{'error':'increase post_max_size and upload_max_filesize to $size'}");
}
}
private function toBytes($str)
{
$val = trim($str);
$last = mb_strtolower($str[mb_strlen($str)-1]);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
*/
function save($sFileName)
{
$oInput = fopen("php://input", "r");
$sTemp = tmpfile();
$iRealSize = stream_copy_to_stream($oInput, $sTemp);
fclose($oInput);
if($iRealSize != $this->getSize())
{
return false;
}
$sPath = $this->sFolderPath.$sFileName;
$oTarget = fopen($sPath, "w");
fseek($sTemp, 0, SEEK_SET);
stream_copy_to_stream($sTemp, $oTarget);
fclose($oTarget);
return true;
}
function getName()
{
return isset($_GET[self::GET_NAME])?$_GET[self::GET_NAME]:false;
}
function getSize()
{
if(isset($_SERVER["CONTENT_LENGTH"]))
{
return (int)$_SERVER["CONTENT_LENGTH"];
}
else
{
throw new Exception('Getting content length is not supported.');
}
}
//Returns array('success'=>true) or array('error'=>'error message')
function handleUpload(/*$sUploadDir, $replaceOldFile = false*/)
{
if(!is_writable($this->sFolderPath))
{
return array('error' => "Erreur serveur. Le dossier est prot&eacute;g&eacute; en &eacute;criture");
}
if(!$this->getName())
{
return array('error' => 'Aucun fichier t&eacute;l&eacute;charg&eacute;');
}
$iSize = $this->getSize();
if($iSize == 0)
{
return array('error' => 'Fichier vide');
}
if($iSize > $this->iSizeLimit)
{
return array('error' => 'Fichier trop volumineux');
}
$asPathInfo = pathinfo($this->getName());
$sExt = mb_strtolower($asPathInfo['extension']);
$sExt = ($sExt=='jpg')?'jpeg':$sExt;
if($this->asAllowedExtensions && !in_array($sExt, $this->asAllowedExtensions))
{
$sAuthorizedExts = implode(', ', $this->asAllowedExtensions);
return array('error' => 'Le fichier a une extension invalide, les extensions autoris&eacute;es sont : '.$sAuthorizedExts);
}
//
//$sFileName = $asPathInfo['filename'];
$sFileName = md5(uniqid());
/*
if(!$replaceOldFile){
// don't overwrite previous files that were uploaded
//while (file_exists($sUploadDir . $sFileName . '.' . $sExt)) {
// $sFileName .= rand(10, 99);
//}
if(file_exists($sUploadDir . $sFileName . '.' . $sExt))
{
$sFileName .= date(Databap::DATE_COMPACT_FORMAT);
}
}
*/
if($this->save($sFileName.'.'.$sExt))
{
return array('success'=>true, 'file_name'=>$sFileName.'.'.$sExt);
}
else
{
return array('error'=> 'Erreur server. Impossible de sauvegarder le fichier.');
}
}
}
?>

231
inc/mask.php Normal file
View 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 &agrave; 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);
}
}
?>

601
inc/mysqlmanager.php Normal file
View File

@@ -0,0 +1,601 @@
<?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;
/**
* SQL connection Handle
* @var mysqli
*/
private $oConnection;
private $sDatabase;
private $asOptions;
/**
* Tables & fields descriptions
* 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'=>...))
* @var Array
*/
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->bDebug = 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&eacute;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 emptyTable($sTableName)
{
$this->cleanSql($sTableName);
return $this->setQuery("TRUNCATE ".$sTableName);
}
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 = "";
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)
{
//FIXME 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&eacute;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);
}
//TODO déplacer dans ToolBox::implodeALl
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);
}
}
}
?>

274
inc/procedure.php Normal file
View File

@@ -0,0 +1,274 @@
<?php
/**
* Procedure Manager
* @author franzz
*/
class Procedure extends PhpObject
{
//Constants
const THUMB_MAX_SIZE = 100;
const IMAGE_FOLDER = Databap::DOC_FOLDER;
const IMAGE_FOLDER_TMP = Databap::DOC_TMP_FOLDER;
const IMAGE_FOLDER_THUMB = Databap::DOC_THUMB_FOLDER;
//Objects
private $oMySql;
//Procedure Elements
private $iProcId;
private $iUserId;
private $sTitle;
private $sDescription;
private $dLed;
private $asSteps; // [id_step]=>text
private $asImages; // [id_step][id_image]=>array('name'=>file name, 'desc'=> description)
function __construct($oMySql)
{
parent::__construct(__CLASS__, Settings::DEBUG);
$this->oMySql = $oMySql;
$this->iPrevProcId = 0;
$this->setProcedureId(0);
$this->sTitle = '';
$this->sDescription = '';
$this->dLed = '';
$this->asSteps = array();
$this->asImages = array();
}
public function getProcedureId()
{
return $this->iProcId;
}
public function getProcedureLed()
{
return $this->dLed;
}
public function setProcedureId($iProcId)
{
$this->iProcId = $iProcId;
}
public function inputForm($asPost)
{
//User
$this->iUserId = $asPost['id_user'];
//Titles
$this->sTitle = isset($asPost['title'])?$asPost['title']:'';
$this->sDescription = isset($asPost['description'])?$asPost['description']:'';
//Steps
$sStepPattern = '/c(?P<step_id>\d+)_step_text/u';
$sImagePattern = '/c(?P<step_id>\d+)_(?P<image_id>\d+)_image_(?P<image_info>\w+)/u';
foreach($asPost as $sFormId=>$sValue)
{
//Step Text
preg_match($sStepPattern, $sFormId, $asMatches);
if(isset($asMatches['step_id']))
{
$this->asSteps[$asMatches['step_id']] = $sValue;
}
else
{
preg_match($sImagePattern, $sFormId, $asMatches);
if
(
isset($asMatches['step_id'], $asMatches['image_id'], $asMatches['image_info']) &&
($asMatches['image_info'] == 'name' || $asMatches['image_info']== 'desc')
)
{
$this->asImages[$asMatches['step_id']][$asMatches['image_id']][$asMatches['image_info']] = $sValue;
}
}
}
}
private function isImageSaved($sFileName, $bInTemp=false)
{
$sPath = $bInTemp?self::IMAGE_FOLDER_TMP:self::IMAGE_FOLDER;
return file_exists($sPath.$sFileName);
}
public function checkIntegrity()
{
$asErrors = array();
//Check title
if($this->sTitle=='') $asErrors['title'] = 'Un titre est n&eacute;cessaire';
//Check steps
if(count($this->asSteps)==0)
{
$asErrors['step'] = 'Au moins une &eacute;tape est n&eacute;cessaire';
}
else
{
foreach($this->asSteps as $iStepId=>$sText)
{
if($sText=='')
{
$asErrors['step_'.$iStepId] = 'Une &eacute;tape ne poss&egrave;de pas de texte';
}
}
}
//Check images
foreach($this->asImages as $iStepId=>$asImages)
{
foreach($asImages as $iImageId=>$asFileInfo)
{
//file exists in temp or already stored
if(!$this->isImageSaved($asFileInfo['name']) && !$this->isImageSaved($asFileInfo['name'], true))
{
$asErrors['image_'.$iStepId.'_'.$iImageId] = 'Une image n\'a pas &eacute;t&eacute; t&eacute;l&eacute;charg&eacute;e';
}
if($asFileInfo['desc']=='')
{
$asErrors['image_'.$iStepId.'_'.$iImageId] = 'Une image n\'a pas de nom (description)';
}
}
}
return $asErrors;
}
public function saveProcedure($iPrevProcId)
{
//Add new procedure
$asData = array('title'=>$this->sTitle, 'description'=>$this->sDescription, MySqlManager::getId(Databap::USER_TABLE)=>$this->iUserId);
$iDbProcId = $this->oMySql->insertRow(Databap::PROC_TABLE, $asData);
//Add new steps
$asStepData = $asImgData = array(MySqlManager::getId(Databap::PROC_TABLE)=>$iDbProcId);
foreach($this->asSteps as $iStepId=>$sStepDesc)
{
$asStepData['description'] = $sStepDesc;
$iDbStepId = $this->oMySql->insertRow(Databap::STEP_TABLE, $asStepData);
//Add new images
$asImgData[MySqlManager::getId(Databap::STEP_TABLE)] = $iDbStepId;
foreach($this->asImages[$iStepId] as $asImageInfo)
{
$asImgData['description'] = $asImageInfo['desc'];
$asImgData['file_name'] = $asImageInfo['name'];
$iDbImageId = $this->oMySql->insertRow(Databap::IMG_TABLE, $asImgData);
$this->saveImage($asImgData['file_name']);
}
}
//Add this procedure to the group
$bCreation = ($iPrevProcId==0);
//$this->oMySql->deleteRow(Databap::PROC_TABLE, $this->iPrevProcId);
//$this->oMySql->updateRow(Databap::PROC_TABLE, $iPrevProcId, array('refer_id'=>$iDbProcId));
$iReferId = $bCreation?$iDbProcId:$this->oMySql->selectValue(Databap::PROC_TABLE, 'refer_id', $iPrevProcId);
$this->oMySql->updateRow(Databap::PROC_TABLE, $iDbProcId, array('refer_id'=>$iReferId));
//Update new Procedure Id
//$this->setProcedureId($iDbProcId);
//Reload Procedure
$this->loadProcedure($iDbProcId);
//return creation or edition
return $bCreation;
}
private function saveImage($sFileName)
{
if(!$this->isImageSaved($sFileName))
{
$sTempFilePath = self::IMAGE_FOLDER_TMP.$sFileName;
$sFilePath = self::IMAGE_FOLDER.$sFileName;
//Real Size Image
if(!rename($sTempFilePath, $sFilePath))
{
$this->addError('Unmoveable file : '.$sTempFilePath);
}
//Thumbnail picture
$asResult = ToolBox::createThumbnail($sFilePath, self::THUMB_MAX_SIZE, self::THUMB_MAX_SIZE, self::IMAGE_FOLDER_THUMB, false, Databap::$UPLOAD_IMG_EXTS);
if($asResult['error']!='') $this->addError('Unable to create thumbnail : '.$asResult['out']. '('.$asResult['error'].')');
}
}
public function loadProcedure($iProcId)
{
//Column names
$sProcIdCol = MySqlManager::getId(Databap::PROC_TABLE);
$sStepIdCol = MySqlManager::getId(Databap::STEP_TABLE);
$sImageIdCol = MySqlManager::getId(Databap::IMG_TABLE);
//Get last id available
$this->setProcedureId($iProcId);
$this->refreshProcId();
$asInfo = array('from'=>Databap::PROC_TABLE, 'constraint'=>array($sProcIdCol=>$this->getProcedureId()));
//Load procedure info
$asResult = $this->oMySql->selectRow(Databap::PROC_TABLE, $asInfo['constraint']);
$this->sTitle = $asResult['title'];
$this->sDescription = $asResult['description'];
$this->iUserId = $asResult[MySqlManager::getId(Databap::USER_TABLE)];
$this->dLed = $asResult['led'];
//Load steps info
$asInfo['from'] = Databap::STEP_TABLE;
$this->asSteps = $this->oMySql->selectRows($asInfo, true, $sStepIdCol);
//Load images info
$asInfo['from'] = Databap::IMG_TABLE;
foreach($this->oMySql->selectRows($asInfo) as $asRow)
{
$this->asImages[$asRow[$sStepIdCol]][$asRow[$sImageIdCol]]['name'] = $asRow['file_name'];
$this->asImages[$asRow[$sStepIdCol]][$asRow[$sImageIdCol]]['desc'] = $asRow['description'];
}
}
public function getProcedure()
{
// [id_step]=>text
// [id_step][id_image]=>array('name'=>file name, 'desc'=> description)
/*
$asSteps = $asImages = array();
$iLocalStepId = 1;
foreach($this->asSteps as $iStepId=>$sStepDesc)
{
$asSteps[$iLocalStepId] = $sStepDesc;
if(array_key_exists($iStepId, $this->asImages))
{
$asImages[] =
}
$iLocalStepId++;
}*/
return array( 'proc_id'=>$this->iProcId,
'id_user'=>$this->iUserId,
'title'=>Databap::getDescriptionFormat($this->sTitle),
'description'=>Databap::getDescriptionFormat($this->sDescription),
'led'=>Databap::getDateFormat($this->dLed),
'steps'=>$this->asSteps,
'images'=>$this->asImages);
}
private function refreshProcId()
{
/*
$iReferId = $this->getProcedureId();
do
{
$iProcId = $iReferId;
$iReferId = $this->oMySql->selectValue(Databap::PROC_TABLE, 'refer_id', $iProcId);
}
while($iReferId!=0);
$this->setProcedureId($iProcId);
*/
$iReferId = $this->oMySql->selectValue(Databap::PROC_TABLE, 'refer_id', $this->getProcedureId());
$sSelect = "MAX(".MySqlManager::getId(Databap::PROC_TABLE).")";
$iProcId = $this->oMySql->selectValue(Databap::PROC_TABLE, $sSelect, array('refer_id'=>$iReferId));
$this->setProcedureId($iProcId);
}
}
?>

267
inc/reader.php Normal file
View File

@@ -0,0 +1,267 @@
<?php
/**
* Abap Reader
* @author franzz
*/
class Reader
{
//objects
//private $oMask;
//general
private $sCode;
private $bImprovedColoring;
//Special Wors / Chars
private $asAbap;
//constants
const CASE_SENSITIVE = false;
const NOT_FOUND = '* Code introuvable...';
function __construct($sCode, $bImprovedColoring = false)
{
//settings
$this->bImprovedColoring = $bImprovedColoring;
//get code in db
$this->sCode = $sCode;
if($this->sCode=='')
{
$this->sCode = self::NOT_FOUND;
}
//ABAP key words and chars
$this->asAbap = array
(
'word'=>array
(
'wCore'=>array( /*'&lt;icon&gt;','&lt;itab&gt;',*/'ABBREVIATED','ABSTRACT','ABSTRACTFINAL','ACCEPT','ACCEPTING','ACCORDING','ACTUAL','ADD',
'ADD-CORRESPONDING','ADDITIONS','ADJACENT','ALIASES','ALL','ALLOCATE','ANALYZER', 'AND','APPEND','APPENDING','AS',
'ASCENDING','ASCENDINGDESCENDING','AT','ATTRIBUTE','AUTHORITY-CHECK','BACKGOUND','BEFORE','BEGIN','BETWEEN',
'BIGLITTLE','BINARY','BIT','BLANK','BLOCK','BREAK-POINT','BY','BYPASSING','BYTE','BYTECHARACTER','CASE',
'CASERESPECTING','CASTING','CENTERED','CHAIN','CHANGE','CHANGING','CHARACTER','CHECK','CHECKBOX',
'CHECKBOXSYMBOLICONLINE','CLASS','CLASS-DATA','CLASS-EVENTS','CLASS-METHODS','CLEANUP','CLEAR','CLIENT','CLOCK',
'CODE','COL_BACKGROUND','COL_HEADING','COL_NORMAL','COL_TOTAL','COLLECT','COLOR','COLUMN','COMMENT','COMMIT',
'COMMON','COMMUNICATION','COMPARING','COMPONENTS','COMPUTE','CONCATENATE','CONDENSE','CONSTANTS','CONTEXT',
'CONTEXTS','CONTINUE','CONTROL','CONTROLS','CONVERSION','CONVERT','COUNTRY','COUNTY','CURRENT','CURSOR',
'CUSTOMER-FUNCTION','DATA','DATABASE','DATASET','DATE','DEALLOCATE','DECIMALS','DEFAULT','DEFAULTUTF-8NON-UNICODE',
'DEFERRED','DEFINE','DEFINING','DEFINITION','DELETE','DELETING','DEMAND','DESCENDING','DESCRIBE','DESTINATION',
'DIALOG','DIRECTORY','DISTANCE','DISTINCT','DIVIDE-CORRESPONDING','DO','DUPLICATE','DUPLICATES','DURING','DYNAMIC',
'EDIT','EDITOR-CALL','ELSE','ELSEIF','ENCODING','END','ENDAT','ENDCASE','ENDCATCH','ENDCHAIN','ENDCLASS','ENDDO',
'ENDEXEC','ENDFORM','ENDFUNCTION','ENDIAN','ENDIF','ENDING','ENDINTERFACE','ENDLOOP','ENDMETHOD','ENDMODULE',
'ENDON','ENDPROVIDE','ENDSELECT','ENDTRY','ENDWHILE','END-OF_FILE','END-OF-DEFINITION','END-OF-PAGE',
'END-OF-SELECTION','ENTRIES','EQ','ERRORS','EVENT','EVENTS','EXCEPTION','EXCEPTIONS','EXCEPTION-TABLE','EXCLUDE',
'EXCLUDING','EXEC','EXIT','EXIT-COMMAND','EXPORT','EXPORTING','EXTENDED','EXTRACT','FETCH','FIELD','FIELD-GROUPS',
'FIELDSNO','FIELD-SYMBOLS','FILTER','FINAL','FIND','FIRST','FOR','FORM','FORMAT','FORWARDBACKWARD','FOUND','FRAME',
'FREE','FRIENDS','FROM','FUNCTION','FUNCTION-POOL','GE','GET','GIVING','GROUP','GT','HANDLER','HASHED','HAVING',
'HEADER','HEADING','HELP-ID','HIDE','HIGHLOW','HOLD','HOTSPOT','ID','IF','IGNORING','IMMEDIATELY','IMPLEMENTATION',
'IMPORT','IMPORTING','IN','INCREMENT','INDEX','INDEX-LINE','INHERITING','INIT','INITIAL','INITIALIZATION','INNER',
'INNERLEFT','INSERT','INSTANCES','INTENSIFIED','INTERFACE','INTERFACES','INTERVALS','INTO','INTOAPPENDING',
'INVERTED-DATE','IS','ITAB','JOIN','KEEPING','KEY','KEYS','KIND','LANGUAGE','LAST','LE','LEAVE','LEFT',
'LEFT-JUSTIFIED','LEFTRIGHT','LEFTRIGHTCIRCULAR','LEGACY','LENGTH','LIKE','LINE','LINE-COUNT','LINES','LINES',
'LINE-SELECTION','LINE-SIZE','LIST','LIST-PROCESSING','LOAD','LOAD-OF-PROGRAM','LOCAL','LOCALE','LOOP','LT',
'MARGIN','MARK','MASK','MATCH','MAXIMUM','MEMORY','MESSAGE','MESSAGE-ID','MESSAGES','METHOD','METHODS','MOD','MODE',
'MODEIN','MODIF','MODIFIER','MODIFY','MODULE','MOVE','MOVE-CORRESPONDING','MULTIPLY-CORRESPONDING','NE','NEW',
'NEW-LINE','NEW-PAGE','NEXT','NODES','NODETABLE','NO-DISPLAY','NO-EXTENSION','NO-GAP','NO-GAPS',
'NO-HEADINGWITH-HEADING','NON','NO-SCROLLING','NO-SCROLLINGSCROLLING','NOT','NO-TITLEWITH-TITLE','NO-ZERO','NUMBER',
'OBJECT','OBLIGATORY','OCCURENCE','OCCURENCES','OCCURS','OF','OFF','OFFSET','ON','ONLY','ONOFF','OPEN','OPTION',
'OPTIONAL','OR','ORDER','OTHERS','OUTPUT-LENGTH','OVERLAY','PACK','PACKAGE','PAGE','PAGELAST','PAGEOF','PAGEPAGE',
'PAGES','PARAMETER','PARAMETERS','PARAMETER-TABLE','PART','PERFORM','PERFORMING','PFN','PF-STATUS','PLACES',
'POS_HIGH','POS_LOW','POSITION','POSITIONS','PRIMARY','PRINT','PRINT-CONTROL','PRIVATE','PROCESS','PROGRAM',
'PROPERTY','PROTECTED','PROVIDE','PUBLIC','PUBLICPROTECTEDPRIVATE','PUSHBUTTON','PUT','QUICKINFO','RADIOBUTTON',
'RAISE','RAISING','RANGE','RANGES','READ','RECEIVE','RECEIVING','REDEFINITION','REFERENCE','REFRESH','REJECT',
'RENAMING','REPLACE','REPLACEMENT','REPORT','RESERVE','RESET','RESOLUTION','RESULTS','RETURN','RETURNING','RIGHT',
'RIGHT-JUSTIFIED','ROLLBACK','ROWS','RUN','SCAN','SCREEN','SCREEN-GROUP1','SCREEN-GROUP2','SCREEN-GROUP3',
'SCREEN-GROUP4','SCREEN-GROUP5','SCREEN-INPUT','SCREEN-INTENSIFIED','SCROLL','SCROLL-BOUNDARY','SEARCH','SECTION',
'SELECT','SELECTION','SELECTIONS','SELECTION-SCREEN','SELECTION-SET','SELECTION-TABLE','SELECT-OPTIONS','SEND',
'SEPARATED','SET','SHARED','SHIFT','SIGN','SINGLE','SINGLEDISTINCT','SIZE','SKIP','SORT','SORTABLE','SPACE',
'SPECIFIED','SPLIT','SQL','STABLE','STAMP','STANDARD','START','STARTING','START-OF-SELECTION','STATICS','STEP-LOOP',
'STOP','STRLEN','STRUCTURE','SUBMIT','SUBTRACT','SUBTRACT-CORRESPONDING','SUFFIX','SUPPLY','SUPPRESS','SYMBOLS',
'SYSTEM-EXCEPTIONS','TABLE','TABLES','TABLEVIEW','TASK','TEXT','THEN','TIME','TIMES','TITLE','TITLEBAR','TO',
'TOPIC','TOP-OF-PAGE','TRAILING','TRANSACTION','TRANSFER','TRANSLATE','TRY','TYPE','TYPELIKE','TYPE-POOL',
'TYPE-POOLS','TYPES','ULINE','UNION','UNIQUE','UNTIL','UP','UPDATE','UPPERLOWER','USER-COMMAND','USING','VALUE',
'VALUES','VARY','VARYING','VERSION','VIA','WAIT','WHEN','WHERE','WHILE','WINDOW','WITH','WORK','WRITE','ZONE','ADD',
'ADD-CORRESPONDING','APPEND','BREAK-POINT','CORRESPONDING','FIELDS','ASSIGN','AVG','BACK','CALL','CATCH','CHANGE',
'CHECK','CLEAR','CLOSE','COMMIT','COMPUTE','COUNT','CREATE','DATASET','DELETE','DESCRIBE','DIVIDE','DO','ELSE',
'ELSEIF','EXIT','FIND','FOR','FORMAT','GET','IF','INCLUDE','LOOP','MAX','MESSAGE','METHOD','MIN','MODIFY','MOVE',
'MULTIPLY','NEW-PAGE','OBJECT','OPEN','ORDER','READ','SORT','SUM','TRANSLATE','ULINE','WORK','WRITE','XSTRLEN',
'ABS','ACOS','AFTER','ALL','AND','AS','ASIN','ASSIGNING','AT','ATAN','BEGIN','BUFFER','BY','CA','CEIL','CENTERED',
'CN','CO','COLOR','COMPARING','COMPONENT','COS','COSH','CP','CS','DEFAULT','END','EQ','EXP','FLOOR','FRAC','GE',
'GROUP','GT','ICON','IN','INDEX','INNER','INTENSIFIED','INTO','IS','JOIN','LE','LEADING','LEAVE','LEFT','LIKE',
'LOG','LOG10','LOWER','LT','M','MOD','NA','NE','NOT','NP','NS','O','OF','OFF','ON','OR','OTHERS','OUTER','REF',
'RIGHT','SIGN','SIN','SINH','SQRT','TABLE','TABLENAME','TAN','TANH','TITLE','TO','TRAILING','TRUNC','TYPE','UPPER',
'USING','VALUE','WITH', 'TRANSPORTING', 'TYPE-POOLS'),
'wBwCore'=>array('SOURCE_PACKAGE', 'RESULT_PACKAGE', '<SOURCE_FIELDS>', '<RESULT_FIELDS>'),
'cOperator'=>array('(', ')', ',', '.', ':', '-', '~', '[', ']', '&lt;', '&gt;'),
'cCalculation'=>array('+', '-', '*', '/', '=', '(', ')'),
'cComment'=>array('*'),
'cPartComment'=>array('&quot;'),
'cString'=>array('&quot;', '&#039;'),
'iNumber'=>array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'),
'wExpand'=>array('loop'=>'endloop', 'if'=>'endif'),
'wGlobal'=>array('SY'),
'wCodePart'=>array('main', 'global', 'global2')
),
'color'=>array
(
'wCore'=>'core',
'wBwCore'=>'core',
'cOperator'=>'operator',
'cCalculation'=>'operator',
'cComment'=>'comment',
'cPartComment'=>'comment',
'cString'=>'string',
'iNumber'=>'number',
'wExpand'=>'expand',
'wGlobal'=>'glogal',
'wCodePart'=>'code_part'
)
);
}
private function getWords($sKey)
{
return $this->asAbap['word'][$sKey];
}
private function getColor($sKey)
{
return $this->asAbap['color'][$sKey];
}
private function addColoring()
{
//Safe characters
$sCode = $this->convText2Html($this->sCode);
$sServName = $_GET['serv_name'];
$sSafeRexExServName = preg_quote(str_replace('http://', '', $sServName), '/');
$asLines = explode("\n", $sCode);
$asLineClasses = array();
$iOffSet = 0;
//building lines
foreach($asLines as $iLineNb=>$sLine)
{
/* Code ref:
* <li id="#line_nb#" class="#li_class#">
* <span class="expand_line">
* <span id="#expand_id#" class="#expand_class#">-</span>
* </span>
* <span class="#code_class#">#line#</span>
* </li>
*/
$sLiClass = $sExpandSign = $sCodeClass = $sExpandHtml = $sExpandButton = '';
$sFirstWord = $this->getFirstWord($sLine);
$sFirstChar = $this->getFirstChar($sLine);
//Apply current classes
$sLiClass = implode(' ', $asLineClasses);
//Expanding starting/ending point
if(in_array($sFirstWord, array_keys($this->getWords('wExpand')))) //start
{
$iLoopId = count($asLineClasses)+$iOffSet;
$asLineClasses[] = 'loop'.$iLoopId;
$sExpandButton = '<input type="button" id="expand_loop'.$iLoopId.'" class="minus" value="" />';
}
elseif(in_array($sFirstWord, $this->getWords('wExpand'))) //end
{
array_pop($asLineClasses);
$iOffSet++;
$sExpandButton = '<span></span>';
}
//Enlarge line
//if(mb_strpos($sLine, $sServName) !== false) $sLiClass .= ' bigline';
//comments (entire line)
$sCodeClass = (in_array($sFirstChar, $this->getWords('cComment')))?'comment':'code';
//Internal & external Urls
$sLine = Toolbox::findReplaceLinks($sLine);
$asColoredLines[] = '<li id="'.($iLineNb+1).'" class="round_right '.$sLiClass.'"><span class="expand_line">'.$sExpandButton.'</span><span class="'.$sCodeClass.'">'.$sLine.'</span></li>';
}
$sCode = implode('', $asColoredLines);
//Strings
foreach($this->getWords('cString') as $sStringWord)
{
$sPattern = '/>([^<]*?)'.$sStringWord.'([^<]*?)'.$sStringWord.'/u';
$sCode = preg_replace($sPattern, '>$1<span class="string">'.$sStringWord.'$2'.$sStringWord.'</span>', $sCode);
}
//Part comment
$sPattern = '/>([^<]*)\&quot\;([^<]*)\<\/span\>\<\/li\>/u';
$sCode = preg_replace($sPattern, '>$1<span class="comment">&quot;$2</span>', $sCode);
//Global / Main
$sPattern = '/>\*\ \[('.implode('|', $this->getWords('wCodePart')).')\]/u';
$sCode = preg_replace($sPattern, '><span class="code_part">&#62; $1</span>', $sCode);
//Core Words
foreach($this->getWords('wCore') as $sCoreWord)
{
$sCoreWord = mb_strtolower($sCoreWord);
$sPattern = '/>(([^<]*)([^\w&<]{1})|.{0})('.$sCoreWord.')([\W])/u';
$sCode = preg_replace($sPattern, '>$1<span class="core">$4</span>$5', $sCode);
}
//$sCoreWords = str_replace(' ', '\ ', implode('|', array_map('mb_strtolower', $this->getWords('wCore'))));
//$sPattern = '/>(([^<]*)([^\w<]{1})|.{0})('.$sCoreWords.')(?=[\W])/U';
//$sCode = preg_replace($sPattern, '>$1<span class="core">$4</span>', $sCode);
//Operators
//TODO distinguer operator / calculation
$asOperators = array_unique(array_merge($this->getWords('cOperator'), $this->getWords('cCalculation')));
foreach($asOperators as $sOpWord)
{
$sPattern = '/>([^<]*)\\'.$sOpWord.'/u';
$sCode = preg_replace($sPattern, '>$1<span class="operator">'.$sOpWord.'</span>', $sCode);
}
//$sPattern = '/>([^<]*)['.implode(array_map('mb_strtolower', ($this->getWords('cOperator')))).']/';
//echo $sPattern;
//$sCode = preg_replace($sPattern, '>$1<span class="operator">$2$3</span>', $sCode);
//Numbers
$sPreChar = '\\'.implode('\\', $this->getWords('cCalculation')).'\s';
$sPattern = '/>((([^<]*)['.$sPreChar.']{1})|.{0})([0-9]+)([\W])/u';
$sCode = preg_replace($sPattern, '>$1<span class="number">$4</span>$5', $sCode);
return $sCode;
}
private static function getFirstWord($sText)
{
return mb_strstr(str_replace('.', ' ', trim($sText)), ' ', true);
}
private static function getFirstChar($sText)
{
return mb_substr(str_replace('.', ' ', trim($sText)), 0, 1);
}
private function addColor(&$sText, $sWord, $sClassColor)
{
$sText = str_replace($sWord, '<span class="'.$sClassColor.'">'.$sWord.'</span>', $sText);
}
private static function getColoredWord($sWord, $sClass)
{
return '<span class="'.$sClass.'">'.$sWord.'</span>';
}
public static function convText2Html($sCode)
{
return htmlspecialchars(mb_strtolower($sCode), ENT_QUOTES);
}
public function getColoredCode()
{
return $this->addColoring();
}
}
?>

View File

@@ -16,7 +16,7 @@ class Feed extends PhpObject {
public function __construct($asDesc, $asItems=array())
{
parent::__construct();
parent::__construct(__CLASS__, Settings::DEBUG);
if(!array_key_exists('link', $asDesc))
{
$asDesc['link'] = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'].'/rss';

254
inc/searchengine.php Normal file
View File

@@ -0,0 +1,254 @@
<?php
/**
* Search Engine : Search through all types of databap documents
*
* Procedure to add a new type in the search
* - Add type in Databap->getItemTables()
* - Add type in the index builder : SearchEngine->buildIndex()
* - Add type in item info : SearchEngine->setItemInfo()
* - Add type in Databap->getItemList() and create a Databap->get<type>info()
* - Add type text in Databap->getProfile()
* - Consider the message types : add + edit in Databap->getMessages() and in chat.html
*/
class SearchEngine extends PhpObject
{
//Objects
private $oMySql;
//variables
private $asWords;
private $iLevelMax;
private $asItemRanks;
private $asItemInfos;
private $asUserInfos;
//Constants
const RESULT_A_PAGE = 20;
const KEYWORDS_SEPARATOR = ' ';
function __construct($oMySql)
{
parent::__construct(__CLASS__, Settings::DEBUG);
$this->oMySql = $oMySql;
$this->asWords = $this->setWords('');
$this->asItemRanks = array();
$this->asItemInfos = array();
$this->asUserInfos = array();
}
public function buildIndex($iItemId, $sType)
{
//Build keywords
switch($sType)
{
case Databap::CODE_TYPE:
$asItemData = $this->oMySql->selectRow(Databap::CODE_TABLE, $iItemId);
$asWords = array($asItemData[MySqlManager::getText(Databap::CODE_TABLE)], $asItemData['description']);
break;
case Databap::PROC_TYPE:
$sItemIdCol = MySqlManager::getId(Databap::PROC_TABLE);
$asItemData = $this->oMySql->selectRow(Databap::PROC_TABLE, $iItemId);
$asItemStepsData = $this->oMySql->selectRows(array('select'=>'description', 'from'=>Databap::STEP_TABLE, 'constraint'=>array($sItemIdCol=>$iItemId)));
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title']) + $asItemStepsData;
break;
case Databap::ART_TYPE:
$asItemData = $this->oMySql->selectRow(Databap::ART_TABLE, $iItemId);
$asWords = array($asItemData['first_name'], $asItemData['last_name'], $asItemData['title']);
break;
case Databap::DOC_TYPE:
$sItemIdCol = MySqlManager::getId(Databap::DOC_TABLE);
$asItemData = $this->oMySql->selectRow(Databap::DOC_TABLE, $iItemId);
$asItemFilesData = $this->oMySql->selectRows(array('select'=>'description', 'from'=>Databap::FILE_TABLE, 'constraint'=>array($sItemIdCol=>$iItemId)));
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title']) + $asItemFilesData;
break;
case Databap::TABLE_TYPE:
$asItemData = $this->oMySql->selectRow(Databap::TABL_TABLE, $iItemId);
$asWords = array('desc'=>$asItemData['description'], 'title'=>$asItemData['title'], 'keywords'=>$asItemData['keywords'], 'system'=>$asItemData['system']);
break;
default:
$this->addError('function '.__FUNCTION__.'(): Incorrect type "'.$sType.'"');
break;
}
$sWords = implode(self::KEYWORDS_SEPARATOR, $asWords);
$sWords = mb_strtolower(str_replace("\n", self::KEYWORDS_SEPARATOR, $sWords));
$sWords = preg_replace('/(\W+)/u', self::KEYWORDS_SEPARATOR, $sWords); //remove all non-word characters
//Add / Modify search database
$asData = array('id_item'=>$iItemId, 'type'=>$sType, 'refer_id'=>(array_key_exists('refer_id', $asItemData)?$asItemData['refer_id']:$iItemId), 'keywords'=>$sWords);
$this->oMySql->insertUpdateRow(Databap::SEARCH_TABLE, $asData, array('id_item', 'type'));
}
public function setWords($sSearchWords)
{
$this->asWords = $this->getParsedWords($sSearchWords);
$this->iLevelMax = count($this->asWords);
$this->setResults();
}
/**
* TODO Customized item preview
$sCodeLines = implode("\n...\n", $this->getCodeInfo($iItemId, 'code'));
$oCode = new Reader($sCodeLines);
$sCodeLines = $oCode->getColoredCode();
*/
private function setItemInfo($iSearchId, $iItemType, $iItemId)
{
if(!array_key_exists($iSearchId, $this->asItemInfos))
{
switch($iItemType)
{
case Databap::CODE_TYPE:
$sItemTable = Databap::CODE_TABLE;
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'description', 'led');
break;
case Databap::PROC_TYPE:
$sItemTable = Databap::PROC_TABLE;
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
break;
case Databap::ART_TYPE:
$sItemTable = Databap::ART_TABLE;
$asItemFields = array('first_name', 'last_name', 'title AS description', 'led');
break;
case Databap::DOC_TYPE:
$sItemTable = Databap::DOC_TABLE;
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
break;
case Databap::TABLE_TYPE:
$sItemTable = Databap::TABL_TABLE;
$asItemFields = array(MySqlManager::getId(Databap::USER_TABLE), 'title AS description', 'led');
break;
}
$this->asItemInfos[$iSearchId] = $this->oMySql->selectRow($sItemTable, $iItemId, $asItemFields);
$this->asItemInfos[$iSearchId]['type'] = $iItemType;
$this->asItemInfos[$iSearchId]['id_item'] = $iItemId;
}
}
private function getItemInfo($iSearchId, $sInfoName)
{
if(array_key_exists($iSearchId, $this->asItemInfos) && array_key_exists($sInfoName, $this->asItemInfos[$iSearchId]))
return $this->asItemInfos[$iSearchId][$sInfoName];
else return false;
}
private function setUserInfo($iUserId)
{
if($iUserId > 0 && !array_key_exists($iUserId, $this->asUserInfos))
{
$sCompanyIdCol = MySqlManager::getId(Databap::COMP_TABLE);
$this->asUserInfos[$iUserId] = $this->oMySql->selectRow
(
Databap::USER_TABLE,
$iUserId,
array('first_name', 'last_name', $sCompanyIdCol)
);
$this->asUserInfos[$iUserId]['company'] = $this->oMySql->selectValue(Databap::COMP_TABLE, MySqlManager::getText(Databap::COMP_TABLE), $this->asUserInfos[$iUserId][$sCompanyIdCol]);
unset($this->asUserInfos[$iUserId][$sCompanyIdCol]);
}
}
private function getUserInfo($iUserId, $sInfoName)
{
if(array_key_exists($iUserId, $this->asUserInfos) && array_key_exists($sInfoName, $this->asUserInfos[$iUserId]))
return $this->asUserInfos[$iUserId][$sInfoName];
else return false;
}
private function setResults()
{
if($this->iLevelMax > 0)
{
//set Results and Ranking
$aiLevels = range(1, $this->iLevelMax);
arsort($aiLevels);
foreach($aiLevels as $iLevel)
{
//all possibilies at level $iLevel
$iIndex = 0;
while(($iIndex + $iLevel) <= $this->iLevelMax)
{
//building query
$asSequence = array_slice($this->asWords, $iIndex, $iLevel);
$this->oMySql->cleanSql($asSequence);
//$sRegExp = implode('(.{0,2})', $asSequence);
$sRegExp = implode(self::KEYWORDS_SEPARATOR.'?', $asSequence);
$sSequence = implode(self::KEYWORDS_SEPARATOR, $asSequence);
//TODO replace with selectRow()
$sQuery = "SELECT id_search, MAX(id_item) AS id_item, type, keywords FROM searchs WHERE keywords REGEXP '{$sRegExp}' GROUP BY type, refer_id";
//search sequence
$asItems = $this->oMySql->getArrayQuery($sQuery, true);
foreach($asItems as $asItem)
{
$iSearchId = $asItem['id_search'];
$iItemId = $asItem['id_item'];;
$iItemType = $asItem['type'];
$sWords = $asItem['keywords'];
//Calculate bonus points
$sWords = str_replace(self::KEYWORDS_SEPARATOR.$sSequence.self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iSeqCount);
$sWords = str_replace(self::KEYWORDS_SEPARATOR.$sSequence, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iStaCount);
$sWords = str_replace($sSequence.self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR, self::KEYWORDS_SEPARATOR.$sWords.self::KEYWORDS_SEPARATOR, $iEndCount);
$iBonus = $iSeqCount*5 + $iStaCount*2 + $iEndCount;
$this->incItemRank($iSearchId, $iLevel*10+$iBonus);
$this->setItemInfo($iSearchId, $iItemType, $iItemId);
$this->setUserInfo($this->getItemInfo($iSearchId, MySqlManager::getId(Databap::USER_TABLE)));
}
$iIndex++;
}
}
}
}
public function getResults()
{
$asResult = array();
//Mixing info
arsort($this->asItemRanks);
foreach($this->asItemRanks as $iSearchId=>$iRank)
{
$iUserId = $this->getItemInfo($iSearchId, MySqlManager::getId(Databap::USER_TABLE));
$sFirstName = $this->getUserInfo($iUserId, 'first_name')?$this->getUserInfo($iUserId, 'first_name'):$this->getItemInfo($iSearchId, 'first_name');
$sLastName = $this->getUserInfo($iUserId, 'last_name')?$this->getUserInfo($iUserId, 'last_name'):$this->getItemInfo($iSearchId, 'last_name');
$sCompany = $this->getUserInfo($iUserId, 'company')?$this->getUserInfo($iUserId, 'company'):'SAP';
$asResult[] = array('id_item'=>$this->getItemInfo($iSearchId, 'id_item'),
'type'=>$this->getItemInfo($iSearchId, 'type'),
'description'=>$this->getItemInfo($iSearchId, 'description'),
'rank'=>$iRank,
'name'=>Databap::getNameFormat($sFirstName, $sLastName),
'company'=>Databap::getCompanyFormat($sCompany),
'led'=>Databap::getDateFormat($this->getItemInfo($iSearchId, 'led')));
}
return $asResult;
}
private function incItemRank($iSearchId, $iRank)
{
if(array_key_exists($iSearchId, $this->asItemRanks))
{
$this->asItemRanks[$iSearchId] += $iRank;
}
else
{
$this->asItemRanks[$iSearchId] = $iRank;
}
}
private function getParsedWords($sSearchWords)
{
return array_unique(array_filter(explode(' ', $sSearchWords), array($this, 'checkSearchedWords')));
}
private function checkSearchedWords($sWord)
{
return (mb_strlen($sWord) >= 2);
}
}
?>

312
inc/toolbox.php Normal file
View File

@@ -0,0 +1,312 @@
<?php
/**
* ToolBox - Only static functions missing from php librairy
* @author franzz
* @version 1.1a
*/
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 mb_ucfirst($sText)
{
$sLength = mb_strlen($sText);
$sFirstChar = mb_substr($sText, 0, 1);
$sThen = mb_substr($sText, 1, $sLength - 1);
return mb_strtoupper($sFirstChar).$sThen;
}
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);
}
//TODO implement link pattern
public static function findReplaceLinks($sText, $sLinkPattern='')
{
$sServerPath = substr(str_replace(array('http://', 'https://'), '', $_GET['serv_name']), 0, -1);
//Phase 1 : Identify internal links : merge cases /#code-1 and code 1, destroy link.
$asPatterns = array();
foreach(Databap::$HASH_TO_PAGE as $sAlt=>$sFinal)
{
$asPatterns['`(^|\ )(https?://|)'.$sServerPath.'/?\#'.$sAlt.'\-([\d]+)`sui'] = '$1$4'.$sFinal.' $3';
}
$sText = preg_replace(array_keys($asPatterns), array_values($asPatterns), $sText);
//Phase 2 : Identify remaining links (external)
$asPatterns = array('`((?:https?|ftp)://\S+[[:alnum:]]/?)`sui', '`((?<!//)(www\.\S+[[:alnum:]]/?))`sui');
$asLinks = array('<a href="$1" class="external_link" target="_blank"><i class="fa fa-inline fa-c-share"></i>$1</a> ', '<a href="http://$1" class="external_link" target="_blank"><i class="fa fa-inline fa-c-share"></i>$1</a>');
$sText = preg_replace($asPatterns, $asLinks, $sText);
//Phase 3: rebuild link
$asPatterns = array();
foreach(Databap::$HASH_TO_PAGE as $sAlt=>$sFinal)
{
$asPatterns['`(^|\ )'.$sAlt.'\ ([\d]+)(\ |)`sui'] = '$1<a href="#'.$sFinal.'-$2" target="_blank" class="internal_link round"><i class="fa fa-inline fa-c-'.$sFinal.'"></i>'.$sFinal.' $2</a>$3';
}
$sText = preg_replace(array_keys($asPatterns), array_values($asPatterns), $sText);
//@file_put_contents('log.html', "\n\n".date('r')."\n".$test, FILE_APPEND);
return $sText;
}
public static function getDateTimeDesc($oTime)
{
$iTimeStamp = is_numeric($oTime)?$oTime:strtotime($oTime);
$sCurTimeStamp = time();
$asWeekDays = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');
$asMonths = array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre');
$sSep = '|';
$sFormat = 'Y'.$sSep.'n'.$sSep.'W'.$sSep.'N'.$sSep.'j'.$sSep.'G';
list($sYear, $sMonth, $sWeek, $sWeekDay, $sDay, $sHour) = explode($sSep, date($sFormat, $iTimeStamp));
list($sCurYear, $sCurMonth, $sCurWeek, $sCurWeekDay, $sCurDay, $sCurHour) = explode($sSep, date($sFormat, $sCurTimeStamp));
$sDesc = '';
if($iTimeStamp>$sCurTimeStamp) $sDesc = 'dans le futur';
elseif($sCurTimeStamp-$iTimeStamp<60) $sDesc = 'il y a quelques secondes';
elseif($sCurTimeStamp-$iTimeStamp<60*10) $sDesc = 'il y a quelques minutes';
elseif($sCurTimeStamp-$iTimeStamp<60*20) $sDesc = 'il y a un quart d\'heure';
elseif($sCurTimeStamp-$iTimeStamp<60*50) $sDesc = 'il y a une demi-heure';
elseif($sCurTimeStamp-$iTimeStamp<60*60*2) $sDesc = 'il y a une heure';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24 && $sDay==$sCurDay) $sDesc = 'à '.$sHour.'h';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24) $sDesc = 'hier';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*7 && $sWeek==$sCurWeek) $sDesc = $asWeekDays[$sWeekDay-1];
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*7) $sDesc = $asWeekDays[$sWeekDay-1].' dernier';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*9) $sDesc = 'il y a une semaine';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*12) $sDesc = 'il y a 10 jours';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*16) $sDesc = 'il y a 2 semaines';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*23) $sDesc = 'il y a 3 semaines';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*31 && $sMonth==$sCurMonth) $sDesc = 'le '.$sDay.' '.$asMonths[$sMonth-1];
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*30*2 && $sMonth==($sCurMonth-1)) $sDesc = 'le mois dernier';
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*365 && $sYear==$sCurYear) $sDesc = 'en '.$asMonths[$sMonth-1];
elseif($sCurTimeStamp-$iTimeStamp<60*60*24*365) $sDesc = 'en '.$asMonths[$sMonth-1].' '.$sYear;
elseif($sYear==($sCurYear-1)) $sDesc = 'l\'année dernière';
else $sDesc = 'en '.$sYear;
//return self::mb_ucfirst($sDesc);
return $sDesc;
}
}
?>