Files
mythoughts/config.php
2016-12-16 10:42:04 +13:00

996 lines
25 KiB
PHP
Executable File

<?php
/**
* TODO List
* save before quit / read
* Signature automatique (ajouter dans settings)
* connexion : diary cover + cadenas
* writing pad : open book (2 pages) ou plusieurs feuilles superposées
* separate textarea / text layout
* all hovering / active images on the same one + positioning
* thougt layout ! replace " with image quote
*/
class PhpObject
{
private $asMessageStack;
private $iExtractMode;
const ERROR_TAB = 'error';
const WARNING_TAB = 'warning';
const MODE_ARRAY = 0;
const MODE_TEXT = 1;
const MODE_FILE = 2;
function __construct()
{
$this->asMessageStack = array();
$this->asMessageStack[self::ERROR_TAB] = array();
$this->asMessageStack[self::WARNING_TAB] = array();
$this->iExtractMode = self::MODE_ARRAY;
}
protected function addError($sError)
{
$this->addMessage(self::ERROR_TAB, $sError);
}
protected function addWarning($sWarning)
{
$this->addMessage(self::WARNING_TAB, $sError);
}
private function addMessage($sType, $sMessage)
{
$this->asMessageStack[$sType][] = $sMessage;
}
protected function getCleanErrorStack()
{
return $this->getCleanMessageStack(self::ERROR_TAB);
}
protected function getCleanWarningStack()
{
return $this->getCleanMessageStack(self::WARNING_TAB);
}
private function getCleanMessageStack($sType)
{
switch($this->iExtractMode)
{
case self::MODE_TEXT:
$oMessageStack = implode("\n", $this->asMessageStack[$sType]);
break;
case self::MODE_ARRAY:
$oMessageStack = $this->asMessageStack[$sType];
break;
case self::MODE_FILE:
$oMessageStack = implode("</p><p>", $this->asMessageStack[$sType]);
break;
}
$this->asMessageStack[$sType] = array();
return $oMessageStack;
}
function __destruct()
{
$sErrorStack = $this->getCleanErrorStack();
switch($this->iExtractMode)
{
case self::MODE_TEXT:
echo $sErrorStack;
break;
case self::MODE_ARRAY:
if(count($sErrorStack)>0)
{
pre($sErrorStack, 'Error Stack');
}
break;
case self::MODE_FILE:
if($sErrorStack!='')
{
@file_put_contents('log.html', '<p style="font-weight:bold;">'.date('r')."</p><p>".$sErrorStack.'</p>', FILE_APPEND);
}
break;
}
}
}
class Session extends PhpObject
{
private $iUserId;
private $sLogin;
private $sToken;
private $sPostToken;
private $oMySql;
const SESSION_ID_USER = 'id_user';
const SESSION_USER = 'user';
const SESSION_TOKEN = 'token';
const SESSION_POST_TOKEN = 'post_token';
public function __construct($oMySql)
{
parent::__construct();
$this->iUserId = $this->sLogin = $this->sToken = $this->sPostToken = false;
$this->oMySql = $oMySql;
$this->syncSession();
}
public function getUserId()
{
return $this->iUserId;
}
private function syncSession()
{
if(isset($_SESSION[self::SESSION_ID_USER]))
{
$this->iUserId = $_SESSION[self::SESSION_ID_USER];
}
if(isset($_SESSION[self::SESSION_USER]))
{
$this->sLogin = $_SESSION[self::SESSION_USER];
}
if(isset($_SESSION[self::SESSION_TOKEN]))
{
$this->sToken = $_SESSION[self::SESSION_TOKEN];
}
if(isset($_SESSION[self::SESSION_POST_TOKEN]))
{
$this->sPostToken = $_SESSION[self::SESSION_POST_TOKEN];
}
}
private function setSession($iUserId, $sLogin)
{
$_SESSION[self::SESSION_ID_USER] = $iUserId;
$_SESSION[self::SESSION_USER] = $sLogin;
//Token
$sToken = $this->createToken();
$_SESSION[self::SESSION_TOKEN] = $sToken;
$this->setTokenCookie($sToken);
$this->syncSession();
}
public function register($asData)
{
$sLogin = strtolower($asData['user']);
$sPass = $asData['pass'];
if($sLogin=='' || $sPass=='')
{
$this->addError('Empty mandatory fields (Nickname or password)');
}
elseif(htmlspecialchars($sLogin, ENT_QUOTES)!=$sLogin)
{
$this->addError('Nickname: HTML characters are forbidden');
}
elseif($this->oMySql->selectRow(Db::USERS_TABLE, array('user'=>$sLogin)))
{
$this->addError('Nickname: This is already a user called by that name, choose a different one');
}
else
{
$asData['pass'] = self::encryptPassword($sPass);
$iUserId = $this->oMySql->insertRow(Db::USERS_TABLE, $asData);
return $this->logMeIn($sLogin, $sPass);
}
return false;
}
public function logMeIn($sLogin, $sPass)
{
$bResult = false;
$asUser = $this->oMySql->selectRow(Db::USERS_TABLE, array('user'=>$sLogin));
if(!$asUser)
{
$this->addError('Utilisateur inconnu');
}
elseif(!$this->checkPassword($sPass, $asUser['pass']))
{
$this->addError('mot de pass incorrect');
}
else
{
$this->setSession($asUser[Db::getId(Db::USERS_TABLE)], $sLogin);
$bResult = true;
}
return $bResult;
}
public function isLogguedIn()
{
$bLogguedIn = false;
if($this->iUserId && $this->sLogin && $this->sToken)
{
//check if token is set and valid
if($this->checkToken())
{
//Check if user got a actual account in the database
$bLogguedIn = $this->checkAccount($this->sLogin, $this->iUserId);
}
else
{
$this->addError('Authentication problem, please sign in again');
}
}
return $bLogguedIn;
}
private function checkAccount($sUserName, $iUserId=0)
{
$asConstraints = array('user'=>$sUserName);
if($iUserId>0)
{
$asConstraints[Db::getId(Db::USERS_TABLE)] = $iUserId;
}
return $this->oMySql->selectValue(Db::USERS_TABLE, 'COUNT(1)', $asConstraints);
}
public function logMeOut()
{
$_SESSION = array();
$this->setTokenCookie('', -1);
return session_destroy();
}
private static function encryptPassword($sPass)
{
$sRandomText = 'F_RA-1H"2{bvj)5f?0sd3r#fP,K]U|w}hGiN@(sZ.sDe!7*x/:Mq+&';
for($iIndex=0; $iIndex < strlen($sPass); $iIndex++)
{
$sPass[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sPass[$iIndex];
}
return md5($sPass);
}
private static function createToken()
{
return self::encryptPassword( $_SERVER['HTTP_USER_AGENT'].
$_SERVER['REMOTE_ADDR'].
$_SERVER['REQUEST_TIME'].
strstr(microtime(), ' ', true).
$_SERVER['SERVER_SIGNATURE'].
$_SERVER['SERVER_ADMIN']);
}
//Session Token
private static function setTokenCookie($sToken, $iTime=1)
{
setcookie(self::SESSION_TOKEN, $sToken, time()+60*60*24*$iTime);
$_COOKIE[self::SESSION_TOKEN] = $sToken;
}
private function checkToken()
{
return ($this->sToken && array_key_exists(self::SESSION_TOKEN, $_COOKIE) && $_COOKIE[self::SESSION_TOKEN] == $this->sToken);
}
//Post Token
private function refreshPostToken()
{
$this->sPostToken = self::createToken();
$_SESSION[self::SESSION_POST_TOKEN] = $this->sPostToken;
}
public function getNewPostToken()
{
$this->refreshPostToken();
return $this->sPostToken;
}
public function checkPostToken($sPostToken)
{
return ($this->sPostToken && $sPostToken!='' && $sPostToken == $this->sPostToken);
}
private static function checkPassword($sClearPass, $sEncodedPass)
{
return self::encryptPassword($sClearPass) == $sEncodedPass;
}
}
class Mask extends PhpObject
{
public $sMaskName;
public $sFilePath;
private $sMask;
private $asTags;
private $asPartsSource;
private $aoInstances;
const MASK_FOLDER = 'mask/';
const START_TAG = 'START';
const END_TAG = 'END';
const TAG_MARK = '#';
public function __construct($sFileName='')
{
//init
parent::__construct();
$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 function initFile($sFileName)
{
$sFilePath = self::MASK_FOLDER.$sFileName.'.html';
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\] --\>/', $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 = 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 strpos($this->sMask, $sPartStartPattern) + strlen($sPartStartPattern);
}
private function getPartEndPos($sPartName)
{
$sPartEndPattern = $this->getPartPattern($sPartName, self::END_TAG);
return 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 = &$this->findPart($this, $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);
$oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue);
}
private function &findPart($oMask, $sPartName)
{
if(array_key_exists($sPartName, $oMask->aoInstances))
{
return $oMask;
}
else //not tested
{
foreach($oMask->aoInstances as $sLevelPartName=>$aoInstances)
{
if(!empty($aoInstances))
{
//take last instances
return $this->findPart($oMask->getCurrentInstance($sLevelPartName), $sPartName);
}
}
}
$this->addError('No part found : '.$sPartName);
}
private function getCurrentInstance($sPartName)
{
if(!empty($this->aoInstances[$sPartName]))
{
return end($this->aoInstances[$sPartName]);
}
else
{
return false;
}
}
public function setTag($sTagName, $sTagValue)
{
$this->asTags[$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 array_map_encapsulate($oData, self::TAG_MARK);
}
}
class MyThoughts extends PhpObject
{
//Constants
const URL_DATE_FORMAT = 'Ymd';
const LAYOUT_DATE_FORMAT = 'F \t\h\e jS, Y';
const MYSQL_DATE_FORMAT = 'Y-m-d';
const LAYOUT_TIME_FORMAT = 'G:i';
const WELCOME_MSG_FILE = 'welcome';
//settings
const SETTING_LAYOUT = 'layout';
const LAYOUT_ONE_PAGE = '1';
const LAYOUT_TWO_PAGES = '2';
const SETTING_FONT = 'font';
const FONT_THOUGHTS = 'thoughts';
const FONT_ARIAL = 'Arial';
const FONT_VERDANA = 'Verdana';
const SETTING_SIZE = 'Size';
const SIZE_16 = '16';
const SIZE_18 = '18';
const SIZE_20 = '20';
//Objects
private $oMySql;
private $oSession;
private $oCalendar;
private $asSettings;
//Masks
private $oMainMask;
private $oPageMask;
private $oMenuMask;
function __construct()
{
parent::__construct();
$this->oMySql = new Db();
$this->oSession = new Session($this->oMySql);
$this->oCalendar = new Calendar($this->oMySql, $this->oSession);
$this->oMainMask = new Mask('index');
$this->oPageMask = new Mask();
$this->oMenuMask = new Mask();
$this->asSettings = array();
}
public function logMeOut()
{
$this->oSession->logMeOut();
self::relocate();
}
public function isLogguedIn()
{
return $this->oSession->isLogguedIn();
}
public function checkPostToken($sPostToken)
{
return $this->oSession->checkPostToken($sPostToken);
}
public function setPage($sPage)
{
$this->oPageMask->initFile($sPage);
}
public function setPageTitle($sTitle)
{
$this->oMainMask->setTag('title', $sTitle);
}
public function setCalendarDate($iYear=0, $iMonth=0)
{
$this->oCalendar->setDate($iYear, $iMonth);
}
private static function relocate($sPage='', $asVar=array())
{
$asVar['p'] = $sPage;
header('Location:index.php?'.implodeAll($asVar, '=', '&'));
die();
}
public function updateThought($iThoughtId, $sThought)
{
$asValues = array('thought'=>$this->encodeThought($sThought));
$asConstraints = array( Db::getId(Db::THOUGHTS_TABLE)=>$iThoughtId,
Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId());
$this->oMySql->updateRow(Db::THOUGHTS_TABLE, $asConstraints, $asValues);
}
private function shuffleText($sText)
{
$sRandomText = "let's_mess%a&bit;with~it,!just§for¨the^sake*of-it";
for($iIndex=0; $iIndex < strlen($sText); $iIndex++)
{
$sText[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sText[$iIndex];
}
return $sText;
}
public function activateMenu()
{
$this->oMenuMask->initFile('menu');
}
//settings
public static function getSettingsList()
{
//TODO Save on database (param table)
return array(self::SETTING_FONT, self::SETTING_SIZE, self::SETTING_LAYOUT);
}
private static function getDefaultSetting($sSettingName)
{
switch($sSettingName)
{
case self::SETTING_FONT:
return self::FONT_THOUGHTS;
case self::SETTING_LAYOUT:
return self::LAYOUT_ONE_PAGE;
}
return false;
}
private function getSetting($sSettingName)
{
if(!array_key_exists($sSettingName, $this->asSettings))
{
$asConstraint = array(Db::getText(Db::SETTINGS_TABLE)=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId());
$oValue = $this->oMySql->selectValue(Db::SETTINGS_TABLE, 'value', $asConstraint);
$this->asSettings[$sSettingName] = (!$oValue)?self::getDefaultSetting($sSettingName):$oValue;
}
return $this->asSettings[$sSettingName];
}
private function setSetting($sValue, $sSettingName)
{
$this->oMySql->insertUpdateRow(Db::SETTINGS_TABLE, array('setting'=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId()), array('value'=>$sValue));
}
public function setSettings($asSettings)
{
array_walk($asSettings, array($this, 'setSetting'));
}
/* Pages */
public function logonPage($sPreviousLogin)
{
$this->setPageTitle('Login');
$this->setPage('logon');
$sPreviousLogin = ($sPreviousLogin=='')?'':$sPreviousLogin;
$this->oPageMask->setTag('login', $sPreviousLogin);
}
public function writingPage($iThoughtId=0)
{
$sThought = '';
$iThoughtTime = '';
if($iThoughtId!=0)
{
//load a thought
$asConstraints = array( Db::getId(Db::THOUGHTS_TABLE)=>$iThoughtId,
Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId());
$asThought = $this->oMySql->selectRow(Db::THOUGHTS_TABLE, $asConstraints);
$sThought = $this->decodeThought($asThought['thought']);
$iThoughtTime = 'Saved at '.date(self::LAYOUT_TIME_FORMAT, strtotime($asThought['led']));
}
$this->setPage('write_thought');
$this->oPageMask->setTag('font', $this->getSetting(self::SETTING_FONT));
$this->oPageMask->setTag('size', $this->getSetting(self::SETTING_SIZE));
$this->oPageMask->setTag('thought', $sThought);
$this->oPageMask->setTag('thought_id', $iThoughtId);
$this->oPageMask->setTag('last_saved', $iThoughtTime);
$this->setPageTitle('Talk to me');
}
public function readingPage($iTimeStamp=0)
{
if($iTimeStamp==0)
{
$iTimeStamp = strtotime('now');
}
$sMySqlDate = date(self::MYSQL_DATE_FORMAT, $iTimeStamp);
$sLayoutDate = date(self::LAYOUT_DATE_FORMAT, $iTimeStamp);
$asConstraints = array('DATE(led)'=>$sMySqlDate, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId());
$asThougths = $this->oMySql->selectRows(array('from'=>Db::THOUGHTS_TABLE, 'constraint'=>$asConstraints));
$this->setPage('read_thought');
$this->setPageTitle('Thoughts on '.$sLayoutDate);
$this->oPageMask->setTag('date', $sLayoutDate);
foreach($asThougths as $asThought)
{
$asThoughtParagraphs = explode("\n", $this->decodeThought($asThought['thought']));
$this->oPageMask->newInstance('THOUGHT');
$this->oPageMask->setInstanceTag('THOUGHT', 'time', date(self::LAYOUT_TIME_FORMAT, strtotime($asThought['led'])));
foreach($asThoughtParagraphs as $sParagraph)
{
$asParagraphTags = array('thought_paragraph'=>$sParagraph);
$this->oPageMask->addInstance('THOUGHT_PARA', $asParagraphTags);
}
}
//calendar update
$this->setCalendarDate(date('Y', $iTimeStamp), date('m', $iTimeStamp));
return (count($asThougths)>0);
}
public function settingsPage()
{
$this->setPage('settings');
$this->setPageTitle('Settings');
$asSettingsOptions = array( self::SETTING_LAYOUT => array(
'One extensible page' => self::LAYOUT_ONE_PAGE,
'Two Pages, Diary like' => self::LAYOUT_TWO_PAGES),
self::SETTING_FONT => array(
'AES Crawl' => self::FONT_THOUGHTS,
'Arial' => self::FONT_ARIAL,
'Verdana' => self::FONT_VERDANA),
self::SETTING_SIZE => array(
'16pt' => self::SIZE_16,
'18pt' => self::SIZE_18,
'20pt' => self::SIZE_20));
foreach(self::getSettingsList() as $sSettingName)
{
$this->oPageMask->newInstance('SETTING');
$this->oPageMask->setInstanceTag('SETTING', 'setting_name', $sSettingName);
$sUserSetting = $this->getSetting($sSettingName);
foreach($asSettingsOptions[$sSettingName] as $sOptionName=>$sOptionValue)
{
if($sOptionValue == self::getDefaultSetting($sSettingName))
{
$sOptionName .= ' (Default)';
}
$sSelectedOption = ($sUserSetting==$sOptionValue)?'selected':'';
$asSettingOptions = array( 'setting_option_value'=>$sOptionValue,
'setting_option_selected'=>$sSelectedOption,
'setting_option_name'=>$sOptionName);
$this->oPageMask->addInstance('SETTING_OPTION', $asSettingOptions);
}
}
}
/* Final processes */
private function collectErrors()
{
$asErrors = array_merge($this->getCleanErrorStack(),
$this->oMySql->getCleanErrorStack(),
$this->oSession->getCleanErrorStack(),
$this->oCalendar->getCleanErrorStack(),
$this->oMainMask->getCleanErrorStack(),
$this->oPageMask->getCleanErrorStack(),
$this->oMenuMask->getCleanErrorStack());
//$asErrors = array_map('getCleanErrorStack', array($this, $this->oMySql, $this->oSession, $this->oCalendar, $this->oMainMask, $this->oPageMask, $this->oMenuMask));
//pre($asErrors, 'static error stock', true);
$oErrorMask = new Mask();
if(!empty($asErrors))
{
$oErrorMask->initFile('errors');
foreach($asErrors as $sError)
{
$oErrorMask->addInstance('ERROR', array('error'=>$sError));
}
}
return $oErrorMask->getMask();
}
}
class Calendar extends PhpObject
{
const CAL_YEAR = 'cy';
const CAL_MONTH = 'cm';
private $oMySql;
private $oSession;
private $oMask;
private $iUserId;
private $iYear;
private $iMonth;
function __construct($oMySql, $oSession)
{
parent::__construct();
$this->oMySql = $oMySql;
$this->oSession = $oSession;
$this->oMask = new Mask('calendar');
$this->iYear = 0;
$this->iMonth = 0;
}
public function setDate($iYear=0, $iMonth=0)
{
if($iYear==0)
{
$iYear = date('Y');
}
if($iMonth==0)
{
$iMonth = date('m');
}
$this->iYear = $iYear;
$this->iMonth = $iMonth;
}
private function getThoughts()
{
//TODO essayer avec selectRows
$sQuery = "SELECT DATE_FORMAT(led, '%d') AS day
FROM ".Db::THOUGHTS_TABLE."
WHERE ".Db::getId(Db::USERS_TABLE)." = ".$this->oSession->getUserId()."
AND YEAR(led) = ".$this->iYear."
AND MONTH(led) = ".$this->iMonth."
GROUP BY day
ORDER BY day";
return $this->oMySql->getArrayQuery($sQuery, true);
}
private function getUpdatedLink($asParams)
{
$sCurrentVariables = $_SERVER['QUERY_STRING'];
$asCurrentVariables = explode('&', $sCurrentVariables);
foreach($asCurrentVariables as $sParam)
{
$sKey = strstr($sParam, '=', true);
$sValue = substr(strstr($sParam, '='), 1);
$asVariables[$sKey] = $sValue;
}
return '?'.implodeAll(array_merge($asVariables, $asParams), '=', '&');
}
private function getLink($iOffset)
{
$iTimeStamp = mktime(0, 0, 0, $this->iMonth + $iOffset, 1, $this->iYear);
return $this->getUpdatedLink(array(self::CAL_MONTH=>date('n', $iTimeStamp), self::CAL_YEAR=>date('Y', $iTimeStamp)));
}
private function setMaskItems()
{
//week starting on the sunday : offset = 0, monday : offset = 1
$iOffset = 1;
//days in the month
$iMonthLastDay = date('d', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear));
$asDays = range(1, $iMonthLastDay);
$iDayNb = 1 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)) + $iOffset;
$iCalendarLastDay = $iMonthLastDay + (7 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear))) + $iOffset;
//days with thoughts
$asThoughts = $this->getThoughts();
while($iDayNb < $iCalendarLastDay)
{
$iCurrentDayTimeStamp = mktime(0, 0, 0, $this->iMonth, $iDayNb, $this->iYear);
$sItemDate = date('d', $iCurrentDayTimeStamp);
//new week
if(date('w', $iCurrentDayTimeStamp) == $iOffset)
{
$this->oMask->newInstance('WEEK');
}
//day within month
if(date('n', $iCurrentDayTimeStamp)==$this->iMonth)
{
$bThoughts = in_array($iDayNb, $asThoughts);
$sItemClass = $bThoughts?'full':'empty';
$sItemLink = $bThoughts?$this->getUpdatedLink(array('d'=>date(MyThoughts::URL_DATE_FORMAT, $iCurrentDayTimeStamp), 'p'=>'r')):'#';
$sItemLinkTitle = $bThoughts?'See my thoughts on '.date(MyThoughts::LAYOUT_DATE_FORMAT, $iCurrentDayTimeStamp):'';
}
else
{
$sItemClass = 'disabled';
$sItemLink = '#';
$sItemLinkTitle = '';
}
$this->oMask->addInstance('DAY', array('item_day'=>$sItemDate, 'item_class'=>$sItemClass, 'item_link'=>$sItemLink, 'item_link_title'=>$sItemLinkTitle));
$iDayNb++;
}
//column titles
$asDayNames = array('1'=>'Mon', '2'=>'Tue', '3'=>'Wed', '4'=>'Thu', '5'=>'Fri', '6'=>'Sat', $iOffset?'7':'0'=>'Sun');
ksort($asDayNames);
foreach($asDayNames as $sDayName)
{
$this->oMask->addInstance('TITLE', array('day_name'=>$sDayName));
}
}
public function getCalendar()
{
$sResult = '';
if($this->iYear!=0 && $this->iMonth!=0)
{
$this->oMask->setTag('link_prev', $this->getLink(-1));
$this->oMask->setTag('current_month', date('F', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)));
$this->oMask->setTag('link_next', $this->getLink(1));
$this->setMaskItems();
$sResult = $this->oMask->getMask();
}
return $sResult;
}
}
function arrayKeyFilter($asArray, $sCallBack)
{
$asValidKeys = array_flip(array_filter(array_keys($asArray), $sCallBack));
return array_intersect_key($asArray, $asValidKeys);
}
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_map_encapsulate', $oData, $asChar));
}
else
{
return $sChar.$oData.$sChar;
}
}
function implodeAll($asText, $sKeyValueSeparator='', $sRowSeparator='', $sKeyPre='', $sValuePost=false)
{
if($sValuePost===false)
{
$sValuePost = $sKeyPre;
}
$asCombinedText = array();
foreach($asText as $sKey=>$sValue)
{
$asCombinedText[] = $sKeyPre.$sKey.$sKeyValueSeparator.$sValue.$sValuePost;
}
return implode($sRowSeparator, $asCombinedText);
}
function cleanPost(&$asData)
{
//get rid of magic quotes
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
cleanData($asData, 'stripslashes');
}
}
function cleanData(&$oData, $sCleaningFunc)
{
if(!is_array($oData))
{
$oData = call_user_func($sCleaningFunc, $oData);
}
elseif(!empty($oData))
{
$asKeys = array_map($sCleaningFunc, array_keys($oData));
$asValues = array_map($sCleaningFunc, $oData);
$oData = array_combine($asKeys, $asValues);
}
}
//debug
function pre($sText, $sTitle='Test', $bDie=false, $bLog=false)
{
if($bLog)
{
file_put_contents('log', ($sTitle!=''?$sTitle." :\n":'').print_r($sText, true)."\n\n");
}
echo '<fieldset class="rounded"><legend class="rounded">'.$sTitle.'</legend><pre>'.print_r($sText, true).'</pre></fieldset>';
if($bDie)
{
die('[die() called by the test function '.__FUNCTION__.'()]');
}
}
?>