From 1cd3e2b60b1e4faac462557c8c694e819500c536 Mon Sep 17 00:00:00 2001 From: Jannik Beyerstedt Date: Mon, 29 May 2023 18:48:34 +0200 Subject: [PATCH 1/2] PHP 8: Fix major compatibility issues PHP8 deprecated, that class member variables can be created outside the class definition or constructor, which prevented the code to run at all. Additionally the error handling has changed, which has lead to multiple other errors during the runtime. Finally, strftime was deprecated in PHP 8.1. --- index.php | 4 +- lib/PhpTemplate.php | 2 + lib/helper.php | 3 + lib/less.php/Less.php | 1791 ++++++++++++++-------------- model/Overview.php | 2 + model/Room.php | 12 +- model/RoomSelection.php | 3 + model/RoomTab.php | 3 + model/Schedule.php | 17 +- model/Stream.php | 5 + template/assemblies/feedback.phtml | 2 +- template/assemblies/schedule.phtml | 17 +- template/overview.phtml | 5 +- 13 files changed, 956 insertions(+), 910 deletions(-) diff --git a/index.php b/index.php index 5656f510..2d5a5fd8 100644 --- a/index.php +++ b/index.php @@ -87,7 +87,7 @@ 'conference' => new GenericConference(), )); - if(startswith('//', @$GLOBALS['CONFIG']['BASEURL'])) + if(isset($GLOBALS['CONFIG']['BASEURL']) && startswith('//', @$GLOBALS['CONFIG']['BASEURL'])) { $tpl->set(array( 'httpsurl' => forceslash(forceslash('https:'.$GLOBALS['CONFIG']['BASEURL']).@$GLOBALS['MANDATOR']).forceslash($route).url_params(), @@ -128,7 +128,7 @@ exit; } - @list($mandator, $route) = explode('/', $route, 2); + list($mandator, $route) = array_pad(explode('/', $route, 2), 2, ""); if(!$mandator) { // root requested diff --git a/lib/PhpTemplate.php b/lib/PhpTemplate.php index 1f4b27c1..7fc912b9 100644 --- a/lib/PhpTemplate.php +++ b/lib/PhpTemplate.php @@ -13,10 +13,12 @@ function h($s) class PhpTemplate { private $data = array(); + public $file; public function __construct($file) { $this->file = $file; + $this->data["naked"] = false; } public function set($___data = array()) diff --git a/lib/helper.php b/lib/helper.php index 6a35923b..43c87481 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -36,6 +36,9 @@ function joinpath($parts) function forceslash($url) { + if ($url == NULL) { + $url = ""; + } $url = rtrim($url, '/'); if(strlen($url) > 0) $url .= '/'; diff --git a/lib/less.php/Less.php b/lib/less.php/Less.php index eb33c2db..dfbdaa8a 100644 --- a/lib/less.php/Less.php +++ b/lib/less.php/Less.php @@ -4463,74 +4463,74 @@ public function flatten( $arr, &$out ){ } - - -/** - * Configurable - * - * @package Less - * @subpackage Core - */ -abstract class Less_Configurable { - - /** - * Array of options - * - * @var array - */ - protected $options = array(); - - /** - * Array of default options - * - * @var array - */ - protected $defaultOptions = array(); - - - /** - * Set options - * - * If $options is an object it will be converted into an array by called - * it's toArray method. - * - * @throws Exception - * @param array|object $options - * - */ - public function setOptions($options){ - $options = array_intersect_key($options,$this->defaultOptions); - $this->options = array_merge($this->defaultOptions, $this->options, $options); - } - - - /** - * Get an option value by name - * - * If the option is empty or not set a NULL value will be returned. - * - * @param string $name - * @param mixed $default Default value if confiuration of $name is not present - * @return mixed - */ - public function getOption($name, $default = null){ - if(isset($this->options[$name])){ - return $this->options[$name]; - } - return $default; - } - - - /** - * Set an option - * - * @param string $name - * @param mixed $value - */ - public function setOption($name, $value){ - $this->options[$name] = $value; - } - + + +/** + * Configurable + * + * @package Less + * @subpackage Core + */ +abstract class Less_Configurable { + + /** + * Array of options + * + * @var array + */ + protected $options = array(); + + /** + * Array of default options + * + * @var array + */ + protected $defaultOptions = array(); + + + /** + * Set options + * + * If $options is an object it will be converted into an array by called + * it's toArray method. + * + * @throws Exception + * @param array|object $options + * + */ + public function setOptions($options){ + $options = array_intersect_key($options,$this->defaultOptions); + $this->options = array_merge($this->defaultOptions, $this->options, $options); + } + + + /** + * Get an option value by name + * + * If the option is empty or not set a NULL value will be returned. + * + * @param string $name + * @param mixed $default Default value if confiuration of $name is not present + * @return mixed + */ + public function getOption($name, $default = null){ + if(isset($this->options[$name])){ + return $this->options[$name]; + } + return $default; + } + + + /** + * Set an option + * + * @param string $name + * @param mixed $value + */ + public function setOption($name, $value){ + $this->options[$name] = $value; + } + } /** @@ -4748,6 +4748,7 @@ class Less_Tree_Call extends Less_Tree{ protected $index; protected $currentFileInfo; public $type = 'Call'; + public $parensInOp; public function __construct($name, $args, $index, $currentFileInfo = null ){ $this->name = $name; @@ -5291,6 +5292,7 @@ class Less_Tree_Dimension extends Less_Tree{ public $value; public $unit; public $type = 'Dimension'; + public $parensInOp; public function __construct($value, $unit = null){ $this->value = floatval($value); @@ -5497,6 +5499,8 @@ class Less_Tree_Directive extends Less_Tree{ public $currentFileInfo; public $debugInfo; public $type = 'Directive'; + public $parensInOp; + public $allExtends; public function __construct($name, $value, $rules, $index = null, $currentFileInfo = null, $debugInfo = null ){ $this->name = $name; @@ -6224,6 +6228,7 @@ class Less_Tree_Media extends Less_Tree{ public $currentFileInfo; public $isReferenced; public $type = 'Media'; + public $allExtends; public function __construct($value = array(), $features = array(), $index = null, $currentFileInfo = null ){ @@ -6478,6 +6483,7 @@ class Less_Tree_Operation extends Less_Tree{ public $operands; public $isSpaced; public $type = 'Operation'; + public $parensInOp; /** * @param string $op @@ -6669,6 +6675,7 @@ class Less_Tree_Rule extends Less_Tree{ public $variable; public $currentFileInfo; public $type = 'Rule'; + public $extendOnEveryPath; /** * @param string $important @@ -6795,6 +6802,7 @@ class Less_Tree_Ruleset extends Less_Tree{ public $originalRuleset; public $first_oelements; + public $extendOnEveryPath; public function SetRulesetIndex(){ $this->ruleset_id = Less_Parser::$next_id++; @@ -7951,6 +7959,7 @@ class Less_Tree_Variable extends Less_Tree{ public $currentFileInfo; public $evaluating = false; public $type = 'Variable'; + public $parensInOp; /** * @param string $name @@ -9514,465 +9523,465 @@ public static function toValue($values){ } } - - -/** - * Parser Exception - * - * @package Less - * @subpackage exception - */ -class Less_Exception_Parser extends Exception{ - - /** - * The current file - * - * @var Less_ImportedFile - */ - public $currentFile; - - /** - * The current parser index - * - * @var integer - */ - public $index; - - protected $input; - - protected $details = array(); - - - /** - * Constructor - * - * @param string $message - * @param Exception $previous Previous exception - * @param integer $index The current parser index - * @param Less_FileInfo|string $currentFile The file - * @param integer $code The exception code - */ - public function __construct($message = null, Exception $previous = null, $index = null, $currentFile = null, $code = 0){ - - if (PHP_VERSION_ID < 50300) { - $this->previous = $previous; - parent::__construct($message, $code); - } else { - parent::__construct($message, $code, $previous); - } - - $this->currentFile = $currentFile; - $this->index = $index; - - $this->genMessage(); - } - - - protected function getInput(){ - - if( !$this->input && $this->currentFile && $this->currentFile['filename'] && file_exists($this->currentFile['filename']) ){ - $this->input = file_get_contents( $this->currentFile['filename'] ); - } - } - - - - /** - * Converts the exception to string - * - * @return string - */ - public function genMessage(){ - - if( $this->currentFile && $this->currentFile['filename'] ){ - $this->message .= ' in '.basename($this->currentFile['filename']); - } - - if( $this->index !== null ){ - $this->getInput(); - if( $this->input ){ - $line = self::getLineNumber(); - $this->message .= ' on line '.$line.', column '.self::getColumn(); - - $lines = explode("\n",$this->input); - - $count = count_if_countable($lines); - $start_line = max(0, $line-3); - $last_line = min($count, $start_line+6); - $num_len = strlen($last_line); - for( $i = $start_line; $i < $last_line; $i++ ){ - $this->message .= "\n".str_pad($i+1,$num_len,'0',STR_PAD_LEFT).'| '.$lines[$i]; - } - } - } - - } - - /** - * Returns the line number the error was encountered - * - * @return integer - */ - public function getLineNumber(){ - if( $this->index ){ - // https://bugs.php.net/bug.php?id=49790 - if (ini_get("mbstring.func_overload")) { - return substr_count(substr($this->input, 0, $this->index), "\n") + 1; - } else { - return substr_count($this->input, "\n", 0, $this->index) + 1; - } - } - return 1; - } - - - /** - * Returns the column the error was encountered - * - * @return integer - */ - public function getColumn(){ - - $part = substr($this->input, 0, $this->index); - $pos = strrpos($part,"\n"); - return $this->index - $pos; - } - -} - - -/** - * Chunk Exception - * - * @package Less - * @subpackage exception - */ -class Less_Exception_Chunk extends Less_Exception_Parser{ - - - protected $parserCurrentIndex = 0; - - protected $emitFrom = 0; - - protected $input_len; - - - /** - * Constructor - * - * @param string $input - * @param Exception $previous Previous exception - * @param integer $index The current parser index - * @param Less_FileInfo|string $currentFile The file - * @param integer $code The exception code - */ - public function __construct($input, Exception $previous = null, $index = null, $currentFile = null, $code = 0){ - - $this->message = 'ParseError: Unexpected input'; //default message - - $this->index = $index; - - $this->currentFile = $currentFile; - - $this->input = $input; - $this->input_len = strlen($input); - - $this->Chunks(); - $this->genMessage(); - } - - - /** - * See less.js chunks() - * We don't actually need the chunks - * - */ - protected function Chunks(){ - $level = 0; - $parenLevel = 0; - $lastMultiCommentEndBrace = null; - $lastOpening = null; - $lastMultiComment = null; - $lastParen = null; - - for( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ){ - $cc = $this->CharCode($this->parserCurrentIndex); - if ((($cc >= 97) && ($cc <= 122)) || ($cc < 34)) { - // a-z or whitespace - break; - } - - switch ($cc) { - - // ( - case 40: - $parenLevel++; - $lastParen = $this->parserCurrentIndex; - break; - - // ) - case 41: - $parenLevel--; - if( $parenLevel < 0 ){ - return $this->fail("missing opening `(`"); - } - break; - - // ; - case 59: - //if (!$parenLevel) { $this->emitChunk(); } - break; - - // { - case 123: - $level++; - $lastOpening = $this->parserCurrentIndex; - break; - - // } - case 125: - $level--; - if( $level < 0 ){ - return $this->fail("missing opening `{`"); - - } - //if (!$level && !$parenLevel) { $this->emitChunk(); } - break; - // \ - case 92: - if ($this->parserCurrentIndex < $this->input_len - 1) { $this->parserCurrentIndex++; break; } - return $this->fail("unescaped `\\`"); - - // ", ' and ` - case 34: - case 39: - case 96: - $matched = 0; - $currentChunkStartIndex = $this->parserCurrentIndex; - for ($this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) { - $cc2 = $this->CharCode($this->parserCurrentIndex); - if ($cc2 > 96) { continue; } - if ($cc2 == $cc) { $matched = 1; break; } - if ($cc2 == 92) { // \ - if ($this->parserCurrentIndex == $this->input_len - 1) { - return $this->fail("unescaped `\\`"); - } - $this->parserCurrentIndex++; - } - } - if ($matched) { break; } - return $this->fail("unmatched `" + chr($cc) + "`", $currentChunkStartIndex); - - // /, check for comment - case 47: - if ($parenLevel || ($this->parserCurrentIndex == $this->input_len - 1)) { break; } - $cc2 = $this->CharCode($this->parserCurrentIndex+1); - if ($cc2 == 47) { - // //, find lnfeed - for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) { - $cc2 = $this->CharCode($this->parserCurrentIndex); - if (($cc2 <= 13) && (($cc2 == 10) || ($cc2 == 13))) { break; } - } - } else if ($cc2 == 42) { - // /*, find */ - $lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex; - for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++) { - $cc2 = $this->CharCode($this->parserCurrentIndex); - if ($cc2 == 125) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; } - if ($cc2 != 42) { continue; } - if ($this->CharCode($this->parserCurrentIndex+1) == 47) { break; } - } - if ($this->parserCurrentIndex == $this->input_len - 1) { - return $this->fail("missing closing `*/`", $currentChunkStartIndex); - } - } - break; - - // *, check for unmatched */ - case 42: - if (($this->parserCurrentIndex < $this->input_len - 1) && ($this->CharCode($this->parserCurrentIndex+1) == 47)) { - return $this->fail("unmatched `/*`"); - } - break; - } - } - - if( $level !== 0 ){ - if( ($lastMultiComment > $lastOpening) && ($lastMultiCommentEndBrace > $lastMultiComment) ){ - return $this->fail("missing closing `}` or `*/`", $lastOpening); - } else { - return $this->fail("missing closing `}`", $lastOpening); - } - } else if ( $parenLevel !== 0 ){ - return $this->fail("missing closing `)`", $lastParen); - } - - - //chunk didn't fail - - - //$this->emitChunk(true); - } - - public function CharCode($pos){ - return ord($this->input[$pos]); - } - - - public function fail( $msg, $index = null ){ - - if( !$index ){ - $this->index = $this->parserCurrentIndex; - }else{ - $this->index = $index; - } - $this->message = 'ParseError: '.$msg; - } - - - /* - function emitChunk( $force = false ){ - $len = $this->parserCurrentIndex - $this->emitFrom; - if ((($len < 512) && !$force) || !$len) { - return; - } - $chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom ); - $this->emitFrom = $this->parserCurrentIndex + 1; - } - */ - -} - - -/** - * Compiler Exception - * - * @package Less - * @subpackage exception - */ -class Less_Exception_Compiler extends Less_Exception_Parser{ - -} - -/** - * Parser output with source map - * - * @package Less - * @subpackage Output - */ -class Less_Output_Mapped extends Less_Output { - - /** - * The source map generator - * - * @var Less_SourceMap_Generator - */ - protected $generator; - - /** - * Current line - * - * @var integer - */ - protected $lineNumber = 0; - - /** - * Current column - * - * @var integer - */ - protected $column = 0; - - /** - * Array of contents map (file and its content) - * - * @var array - */ - protected $contentsMap = array(); - - /** - * Constructor - * - * @param array $contentsMap Array of filename to contents map - * @param Less_SourceMap_Generator $generator - */ - public function __construct(array $contentsMap, $generator){ - $this->contentsMap = $contentsMap; - $this->generator = $generator; - } - - /** - * Adds a chunk to the stack - * The $index for less.php may be different from less.js since less.php does not chunkify inputs - * - * @param string $chunk - * @param string $fileInfo - * @param integer $index - * @param mixed $mapLines - */ - public function add($chunk, $fileInfo = null, $index = 0, $mapLines = null){ - - //ignore adding empty strings - if( $chunk === '' ){ - return; - } - - - $sourceLines = array(); - $sourceColumns = ' '; - - - if( $fileInfo ){ - - $url = $fileInfo['currentUri']; - - if( isset($this->contentsMap[$url]) ){ - $inputSource = substr($this->contentsMap[$url], 0, $index); - $sourceLines = explode("\n", $inputSource); - $sourceColumns = end($sourceLines); - }else{ - throw new Exception('Filename '.$url.' not in contentsMap'); - } - - } - - $lines = explode("\n", $chunk); - $columns = end($lines); - - if($fileInfo){ - - if(!$mapLines){ - $this->generator->addMapping( - $this->lineNumber + 1, // generated_line - $this->column, // generated_column - count_if_countable($sourceLines), // original_line - strlen($sourceColumns), // original_column - $fileInfo - ); - }else{ - for($i = 0, $count = count_if_countable($lines); $i < $count; $i++){ - $this->generator->addMapping( - $this->lineNumber + $i + 1, // generated_line - $i === 0 ? $this->column : 0, // generated_column - count_if_countable($sourceLines) + $i, // original_line - $i === 0 ? strlen($sourceColumns) : 0, // original_column - $fileInfo - ); - } - } - } - - if(count_if_countable($lines) === 1){ - $this->column += strlen($columns); - }else{ - $this->lineNumber += count_if_countable($lines) - 1; - $this->column = strlen($columns); - } - - // add only chunk - parent::add($chunk); - } - + + +/** + * Parser Exception + * + * @package Less + * @subpackage exception + */ +class Less_Exception_Parser extends Exception{ + + /** + * The current file + * + * @var Less_ImportedFile + */ + public $currentFile; + + /** + * The current parser index + * + * @var integer + */ + public $index; + + protected $input; + + protected $details = array(); + + + /** + * Constructor + * + * @param string $message + * @param Exception $previous Previous exception + * @param integer $index The current parser index + * @param Less_FileInfo|string $currentFile The file + * @param integer $code The exception code + */ + public function __construct($message = null, Exception $previous = null, $index = null, $currentFile = null, $code = 0){ + + if (PHP_VERSION_ID < 50300) { + $this->previous = $previous; + parent::__construct($message, $code); + } else { + parent::__construct($message, $code, $previous); + } + + $this->currentFile = $currentFile; + $this->index = $index; + + $this->genMessage(); + } + + + protected function getInput(){ + + if( !$this->input && $this->currentFile && $this->currentFile['filename'] && file_exists($this->currentFile['filename']) ){ + $this->input = file_get_contents( $this->currentFile['filename'] ); + } + } + + + + /** + * Converts the exception to string + * + * @return string + */ + public function genMessage(){ + + if( $this->currentFile && $this->currentFile['filename'] ){ + $this->message .= ' in '.basename($this->currentFile['filename']); + } + + if( $this->index !== null ){ + $this->getInput(); + if( $this->input ){ + $line = self::getLineNumber(); + $this->message .= ' on line '.$line.', column '.self::getColumn(); + + $lines = explode("\n",$this->input); + + $count = count_if_countable($lines); + $start_line = max(0, $line-3); + $last_line = min($count, $start_line+6); + $num_len = strlen($last_line); + for( $i = $start_line; $i < $last_line; $i++ ){ + $this->message .= "\n".str_pad($i+1,$num_len,'0',STR_PAD_LEFT).'| '.$lines[$i]; + } + } + } + + } + + /** + * Returns the line number the error was encountered + * + * @return integer + */ + public function getLineNumber(){ + if( $this->index ){ + // https://bugs.php.net/bug.php?id=49790 + if (ini_get("mbstring.func_overload")) { + return substr_count(substr($this->input, 0, $this->index), "\n") + 1; + } else { + return substr_count($this->input, "\n", 0, $this->index) + 1; + } + } + return 1; + } + + + /** + * Returns the column the error was encountered + * + * @return integer + */ + public function getColumn(){ + + $part = substr($this->input, 0, $this->index); + $pos = strrpos($part,"\n"); + return $this->index - $pos; + } + +} + + +/** + * Chunk Exception + * + * @package Less + * @subpackage exception + */ +class Less_Exception_Chunk extends Less_Exception_Parser{ + + + protected $parserCurrentIndex = 0; + + protected $emitFrom = 0; + + protected $input_len; + + + /** + * Constructor + * + * @param string $input + * @param Exception $previous Previous exception + * @param integer $index The current parser index + * @param Less_FileInfo|string $currentFile The file + * @param integer $code The exception code + */ + public function __construct($input, Exception $previous = null, $index = null, $currentFile = null, $code = 0){ + + $this->message = 'ParseError: Unexpected input'; //default message + + $this->index = $index; + + $this->currentFile = $currentFile; + + $this->input = $input; + $this->input_len = strlen($input); + + $this->Chunks(); + $this->genMessage(); + } + + + /** + * See less.js chunks() + * We don't actually need the chunks + * + */ + protected function Chunks(){ + $level = 0; + $parenLevel = 0; + $lastMultiCommentEndBrace = null; + $lastOpening = null; + $lastMultiComment = null; + $lastParen = null; + + for( $this->parserCurrentIndex = 0; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++ ){ + $cc = $this->CharCode($this->parserCurrentIndex); + if ((($cc >= 97) && ($cc <= 122)) || ($cc < 34)) { + // a-z or whitespace + break; + } + + switch ($cc) { + + // ( + case 40: + $parenLevel++; + $lastParen = $this->parserCurrentIndex; + break; + + // ) + case 41: + $parenLevel--; + if( $parenLevel < 0 ){ + return $this->fail("missing opening `(`"); + } + break; + + // ; + case 59: + //if (!$parenLevel) { $this->emitChunk(); } + break; + + // { + case 123: + $level++; + $lastOpening = $this->parserCurrentIndex; + break; + + // } + case 125: + $level--; + if( $level < 0 ){ + return $this->fail("missing opening `{`"); + + } + //if (!$level && !$parenLevel) { $this->emitChunk(); } + break; + // \ + case 92: + if ($this->parserCurrentIndex < $this->input_len - 1) { $this->parserCurrentIndex++; break; } + return $this->fail("unescaped `\\`"); + + // ", ' and ` + case 34: + case 39: + case 96: + $matched = 0; + $currentChunkStartIndex = $this->parserCurrentIndex; + for ($this->parserCurrentIndex = $this->parserCurrentIndex + 1; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) { + $cc2 = $this->CharCode($this->parserCurrentIndex); + if ($cc2 > 96) { continue; } + if ($cc2 == $cc) { $matched = 1; break; } + if ($cc2 == 92) { // \ + if ($this->parserCurrentIndex == $this->input_len - 1) { + return $this->fail("unescaped `\\`"); + } + $this->parserCurrentIndex++; + } + } + if ($matched) { break; } + return $this->fail("unmatched `" + chr($cc) + "`", $currentChunkStartIndex); + + // /, check for comment + case 47: + if ($parenLevel || ($this->parserCurrentIndex == $this->input_len - 1)) { break; } + $cc2 = $this->CharCode($this->parserCurrentIndex+1); + if ($cc2 == 47) { + // //, find lnfeed + for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len; $this->parserCurrentIndex++) { + $cc2 = $this->CharCode($this->parserCurrentIndex); + if (($cc2 <= 13) && (($cc2 == 10) || ($cc2 == 13))) { break; } + } + } else if ($cc2 == 42) { + // /*, find */ + $lastMultiComment = $currentChunkStartIndex = $this->parserCurrentIndex; + for ($this->parserCurrentIndex = $this->parserCurrentIndex + 2; $this->parserCurrentIndex < $this->input_len - 1; $this->parserCurrentIndex++) { + $cc2 = $this->CharCode($this->parserCurrentIndex); + if ($cc2 == 125) { $lastMultiCommentEndBrace = $this->parserCurrentIndex; } + if ($cc2 != 42) { continue; } + if ($this->CharCode($this->parserCurrentIndex+1) == 47) { break; } + } + if ($this->parserCurrentIndex == $this->input_len - 1) { + return $this->fail("missing closing `*/`", $currentChunkStartIndex); + } + } + break; + + // *, check for unmatched */ + case 42: + if (($this->parserCurrentIndex < $this->input_len - 1) && ($this->CharCode($this->parserCurrentIndex+1) == 47)) { + return $this->fail("unmatched `/*`"); + } + break; + } + } + + if( $level !== 0 ){ + if( ($lastMultiComment > $lastOpening) && ($lastMultiCommentEndBrace > $lastMultiComment) ){ + return $this->fail("missing closing `}` or `*/`", $lastOpening); + } else { + return $this->fail("missing closing `}`", $lastOpening); + } + } else if ( $parenLevel !== 0 ){ + return $this->fail("missing closing `)`", $lastParen); + } + + + //chunk didn't fail + + + //$this->emitChunk(true); + } + + public function CharCode($pos){ + return ord($this->input[$pos]); + } + + + public function fail( $msg, $index = null ){ + + if( !$index ){ + $this->index = $this->parserCurrentIndex; + }else{ + $this->index = $index; + } + $this->message = 'ParseError: '.$msg; + } + + + /* + function emitChunk( $force = false ){ + $len = $this->parserCurrentIndex - $this->emitFrom; + if ((($len < 512) && !$force) || !$len) { + return; + } + $chunks[] = substr($this->input, $this->emitFrom, $this->parserCurrentIndex + 1 - $this->emitFrom ); + $this->emitFrom = $this->parserCurrentIndex + 1; + } + */ + +} + + +/** + * Compiler Exception + * + * @package Less + * @subpackage exception + */ +class Less_Exception_Compiler extends Less_Exception_Parser{ + +} + +/** + * Parser output with source map + * + * @package Less + * @subpackage Output + */ +class Less_Output_Mapped extends Less_Output { + + /** + * The source map generator + * + * @var Less_SourceMap_Generator + */ + protected $generator; + + /** + * Current line + * + * @var integer + */ + protected $lineNumber = 0; + + /** + * Current column + * + * @var integer + */ + protected $column = 0; + + /** + * Array of contents map (file and its content) + * + * @var array + */ + protected $contentsMap = array(); + + /** + * Constructor + * + * @param array $contentsMap Array of filename to contents map + * @param Less_SourceMap_Generator $generator + */ + public function __construct(array $contentsMap, $generator){ + $this->contentsMap = $contentsMap; + $this->generator = $generator; + } + + /** + * Adds a chunk to the stack + * The $index for less.php may be different from less.js since less.php does not chunkify inputs + * + * @param string $chunk + * @param string $fileInfo + * @param integer $index + * @param mixed $mapLines + */ + public function add($chunk, $fileInfo = null, $index = 0, $mapLines = null){ + + //ignore adding empty strings + if( $chunk === '' ){ + return; + } + + + $sourceLines = array(); + $sourceColumns = ' '; + + + if( $fileInfo ){ + + $url = $fileInfo['currentUri']; + + if( isset($this->contentsMap[$url]) ){ + $inputSource = substr($this->contentsMap[$url], 0, $index); + $sourceLines = explode("\n", $inputSource); + $sourceColumns = end($sourceLines); + }else{ + throw new Exception('Filename '.$url.' not in contentsMap'); + } + + } + + $lines = explode("\n", $chunk); + $columns = end($lines); + + if($fileInfo){ + + if(!$mapLines){ + $this->generator->addMapping( + $this->lineNumber + 1, // generated_line + $this->column, // generated_column + count_if_countable($sourceLines), // original_line + strlen($sourceColumns), // original_column + $fileInfo + ); + }else{ + for($i = 0, $count = count_if_countable($lines); $i < $count; $i++){ + $this->generator->addMapping( + $this->lineNumber + $i + 1, // generated_line + $i === 0 ? $this->column : 0, // generated_column + count_if_countable($sourceLines) + $i, // original_line + $i === 0 ? strlen($sourceColumns) : 0, // original_column + $fileInfo + ); + } + } + } + + if(count_if_countable($lines) === 1){ + $this->column += strlen($columns); + }else{ + $this->lineNumber += count_if_countable($lines) - 1; + $this->column = strlen($columns); + } + + // add only chunk + parent::add($chunk); + } + } /** @@ -10160,368 +10169,368 @@ public function base64Decode($char){ } } - - -/** - * Source map generator - * - * @package Less - * @subpackage Output - */ -class Less_SourceMap_Generator extends Less_Configurable { - - /** - * What version of source map does the generator generate? - */ - const VERSION = 3; - - /** - * Array of default options - * - * @var array - */ - protected $defaultOptions = array( - // an optional source root, useful for relocating source files - // on a server or removing repeated values in the 'sources' entry. - // This value is prepended to the individual entries in the 'source' field. - 'sourceRoot' => '', - - // an optional name of the generated code that this source map is associated with. - 'sourceMapFilename' => null, - - // url of the map - 'sourceMapURL' => null, - - // absolute path to a file to write the map to - 'sourceMapWriteTo' => null, - - // output source contents? - 'outputSourceFiles' => false, - - // base path for filename normalization - 'sourceMapRootpath' => '', - - // base path for filename normalization - 'sourceMapBasepath' => '' - ); - - /** - * The base64 VLQ encoder - * - * @var Less_SourceMap_Base64VLQ - */ - protected $encoder; - - /** - * Array of mappings - * - * @var array - */ - protected $mappings = array(); - - /** - * The root node - * - * @var Less_Tree_Ruleset - */ - protected $root; - - /** - * Array of contents map - * - * @var array - */ - protected $contentsMap = array(); - - /** - * File to content map - * - * @var array - */ - protected $sources = array(); - protected $source_keys = array(); - - /** - * Constructor - * - * @param Less_Tree_Ruleset $root The root node - * @param array $options Array of options - */ - public function __construct(Less_Tree_Ruleset $root, $contentsMap, $options = array()){ - $this->root = $root; - $this->contentsMap = $contentsMap; - $this->encoder = new Less_SourceMap_Base64VLQ(); - - $this->SetOptions($options); - - $this->options['sourceMapRootpath'] = $this->fixWindowsPath($this->options['sourceMapRootpath'], true); - $this->options['sourceMapBasepath'] = $this->fixWindowsPath($this->options['sourceMapBasepath'], true); - } - - /** - * Generates the CSS - * - * @return string - */ - public function generateCSS(){ - $output = new Less_Output_Mapped($this->contentsMap, $this); - - // catch the output - $this->root->genCSS($output); - - - $sourceMapUrl = $this->getOption('sourceMapURL'); - $sourceMapFilename = $this->getOption('sourceMapFilename'); - $sourceMapContent = $this->generateJson(); - $sourceMapWriteTo = $this->getOption('sourceMapWriteTo'); - - if( !$sourceMapUrl && $sourceMapFilename ){ - $sourceMapUrl = $this->normalizeFilename($sourceMapFilename); - } - - // write map to a file - if( $sourceMapWriteTo ){ - $this->saveMap($sourceMapWriteTo, $sourceMapContent); - } - - // inline the map - if( !$sourceMapUrl ){ - $sourceMapUrl = sprintf('data:application/json,%s', Less_Functions::encodeURIComponent($sourceMapContent)); - } - - if( $sourceMapUrl ){ - $output->add( sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl) ); - } - - return $output->toString(); - } - - /** - * Saves the source map to a file - * - * @param string $file The absolute path to a file - * @param string $content The content to write - * @throws Exception If the file could not be saved - */ - protected function saveMap($file, $content){ - $dir = dirname($file); - // directory does not exist - if( !is_dir($dir) ){ - // FIXME: create the dir automatically? - throw new Exception(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir)); - } - // FIXME: proper saving, with dir write check! - if(file_put_contents($file, $content) === false){ - throw new Exception(sprintf('Cannot save the source map to "%s"', $file)); - } - return true; - } - - /** - * Normalizes the filename - * - * @param string $filename - * @return string - */ - protected function normalizeFilename($filename){ - - $filename = $this->fixWindowsPath($filename); - - $rootpath = $this->getOption('sourceMapRootpath'); - $basePath = $this->getOption('sourceMapBasepath'); - - // "Trim" the 'sourceMapBasepath' from the output filename. - if (! empty($basePath) && strpos($filename, (string) $basePath) === 0) { - $filename = substr($filename, strlen($basePath)); - } - - // Remove extra leading path separators. - if(strpos($filename, '\\') === 0 || strpos($filename, '/') === 0){ - $filename = substr($filename, 1); - } - - return $rootpath . $filename; - } - - /** - * Adds a mapping - * - * @param integer $generatedLine The line number in generated file - * @param integer $generatedColumn The column number in generated file - * @param integer $originalLine The line number in original file - * @param integer $originalColumn The column number in original file - * @param string $sourceFile The original source file - */ - public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $fileInfo ){ - - $this->mappings[] = array( - 'generated_line' => $generatedLine, - 'generated_column' => $generatedColumn, - 'original_line' => $originalLine, - 'original_column' => $originalColumn, - 'source_file' => $fileInfo['currentUri'] - ); - - $this->sources[$fileInfo['currentUri']] = $fileInfo['filename']; - } - - - /** - * Generates the JSON source map - * - * @return string - * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit# - */ - protected function generateJson(){ - - $sourceMap = array(); - $mappings = $this->generateMappings(); - - // File version (always the first entry in the object) and must be a positive integer. - $sourceMap['version'] = self::VERSION; - - - // An optional name of the generated code that this source map is associated with. - $file = $this->getOption('sourceMapFilename'); - if( $file ){ - $sourceMap['file'] = $file; - } - - - // An optional source root, useful for relocating source files on a server or removing repeated values in the 'sources' entry. This value is prepended to the individual entries in the 'source' field. - $root = $this->getOption('sourceRoot'); - if( $root ){ - $sourceMap['sourceRoot'] = $root; - } - - - // A list of original sources used by the 'mappings' entry. - $sourceMap['sources'] = array(); - foreach($this->sources as $source_uri => $source_filename){ - $sourceMap['sources'][] = $this->normalizeFilename($source_filename); - } - - - // A list of symbol names used by the 'mappings' entry. - $sourceMap['names'] = array(); - - // A string with the encoded mapping data. - $sourceMap['mappings'] = $mappings; - - if( $this->getOption('outputSourceFiles') ){ - // An optional list of source content, useful when the 'source' can't be hosted. - // The contents are listed in the same order as the sources above. - // 'null' may be used if some original sources should be retrieved by name. - $sourceMap['sourcesContent'] = $this->getSourcesContent(); - } - - // less.js compat fixes - if( count_if_countable($sourceMap['sources']) && empty($sourceMap['sourceRoot']) ){ - unset($sourceMap['sourceRoot']); - } - - return json_encode($sourceMap); - } - - /** - * Returns the sources contents - * - * @return array|null - */ - protected function getSourcesContent(){ - if(empty($this->sources)){ - return; - } - $content = array(); - foreach($this->sources as $sourceFile){ - $content[] = file_get_contents($sourceFile); - } - return $content; - } - - /** - * Generates the mappings string - * - * @return string - */ - public function generateMappings(){ - - if( !count_if_countable($this->mappings) ){ - return ''; - } - - $this->source_keys = array_flip(array_keys($this->sources)); - - - // group mappings by generated line number. - $groupedMap = $groupedMapEncoded = array(); - foreach($this->mappings as $m){ - $groupedMap[$m['generated_line']][] = $m; - } - ksort($groupedMap); - - $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0; - - foreach($groupedMap as $lineNumber => $line_map){ - while(++$lastGeneratedLine < $lineNumber){ - $groupedMapEncoded[] = ';'; - } - - $lineMapEncoded = array(); - $lastGeneratedColumn = 0; - - foreach($line_map as $m){ - $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn); - $lastGeneratedColumn = $m['generated_column']; - - // find the index - if( $m['source_file'] ){ - $index = $this->findFileIndex($m['source_file']); - if( $index !== false ){ - $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex); - $lastOriginalIndex = $index; - - // lines are stored 0-based in SourceMap spec version 3 - $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine); - $lastOriginalLine = $m['original_line'] - 1; - - $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn); - $lastOriginalColumn = $m['original_column']; - } - } - - $lineMapEncoded[] = $mapEncoded; - } - - $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';'; - } - - return rtrim(implode($groupedMapEncoded), ';'); - } - - /** - * Finds the index for the filename - * - * @param string $filename - * @return integer|false - */ - protected function findFileIndex($filename){ - return $this->source_keys[$filename]; - } - - /** - * fix windows paths - * @param string $path - * @return string - */ - public function fixWindowsPath($path, $addEndSlash = false){ - $slash = ($addEndSlash) ? '/' : ''; - if( !empty($path) ){ - $path = str_replace('\\', '/', $path); - $path = rtrim($path,'/') . $slash; - } - - return $path; - } - + + +/** + * Source map generator + * + * @package Less + * @subpackage Output + */ +class Less_SourceMap_Generator extends Less_Configurable { + + /** + * What version of source map does the generator generate? + */ + const VERSION = 3; + + /** + * Array of default options + * + * @var array + */ + protected $defaultOptions = array( + // an optional source root, useful for relocating source files + // on a server or removing repeated values in the 'sources' entry. + // This value is prepended to the individual entries in the 'source' field. + 'sourceRoot' => '', + + // an optional name of the generated code that this source map is associated with. + 'sourceMapFilename' => null, + + // url of the map + 'sourceMapURL' => null, + + // absolute path to a file to write the map to + 'sourceMapWriteTo' => null, + + // output source contents? + 'outputSourceFiles' => false, + + // base path for filename normalization + 'sourceMapRootpath' => '', + + // base path for filename normalization + 'sourceMapBasepath' => '' + ); + + /** + * The base64 VLQ encoder + * + * @var Less_SourceMap_Base64VLQ + */ + protected $encoder; + + /** + * Array of mappings + * + * @var array + */ + protected $mappings = array(); + + /** + * The root node + * + * @var Less_Tree_Ruleset + */ + protected $root; + + /** + * Array of contents map + * + * @var array + */ + protected $contentsMap = array(); + + /** + * File to content map + * + * @var array + */ + protected $sources = array(); + protected $source_keys = array(); + + /** + * Constructor + * + * @param Less_Tree_Ruleset $root The root node + * @param array $options Array of options + */ + public function __construct(Less_Tree_Ruleset $root, $contentsMap, $options = array()){ + $this->root = $root; + $this->contentsMap = $contentsMap; + $this->encoder = new Less_SourceMap_Base64VLQ(); + + $this->SetOptions($options); + + $this->options['sourceMapRootpath'] = $this->fixWindowsPath($this->options['sourceMapRootpath'], true); + $this->options['sourceMapBasepath'] = $this->fixWindowsPath($this->options['sourceMapBasepath'], true); + } + + /** + * Generates the CSS + * + * @return string + */ + public function generateCSS(){ + $output = new Less_Output_Mapped($this->contentsMap, $this); + + // catch the output + $this->root->genCSS($output); + + + $sourceMapUrl = $this->getOption('sourceMapURL'); + $sourceMapFilename = $this->getOption('sourceMapFilename'); + $sourceMapContent = $this->generateJson(); + $sourceMapWriteTo = $this->getOption('sourceMapWriteTo'); + + if( !$sourceMapUrl && $sourceMapFilename ){ + $sourceMapUrl = $this->normalizeFilename($sourceMapFilename); + } + + // write map to a file + if( $sourceMapWriteTo ){ + $this->saveMap($sourceMapWriteTo, $sourceMapContent); + } + + // inline the map + if( !$sourceMapUrl ){ + $sourceMapUrl = sprintf('data:application/json,%s', Less_Functions::encodeURIComponent($sourceMapContent)); + } + + if( $sourceMapUrl ){ + $output->add( sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl) ); + } + + return $output->toString(); + } + + /** + * Saves the source map to a file + * + * @param string $file The absolute path to a file + * @param string $content The content to write + * @throws Exception If the file could not be saved + */ + protected function saveMap($file, $content){ + $dir = dirname($file); + // directory does not exist + if( !is_dir($dir) ){ + // FIXME: create the dir automatically? + throw new Exception(sprintf('The directory "%s" does not exist. Cannot save the source map.', $dir)); + } + // FIXME: proper saving, with dir write check! + if(file_put_contents($file, $content) === false){ + throw new Exception(sprintf('Cannot save the source map to "%s"', $file)); + } + return true; + } + + /** + * Normalizes the filename + * + * @param string $filename + * @return string + */ + protected function normalizeFilename($filename){ + + $filename = $this->fixWindowsPath($filename); + + $rootpath = $this->getOption('sourceMapRootpath'); + $basePath = $this->getOption('sourceMapBasepath'); + + // "Trim" the 'sourceMapBasepath' from the output filename. + if (! empty($basePath) && strpos($filename, (string) $basePath) === 0) { + $filename = substr($filename, strlen($basePath)); + } + + // Remove extra leading path separators. + if(strpos($filename, '\\') === 0 || strpos($filename, '/') === 0){ + $filename = substr($filename, 1); + } + + return $rootpath . $filename; + } + + /** + * Adds a mapping + * + * @param integer $generatedLine The line number in generated file + * @param integer $generatedColumn The column number in generated file + * @param integer $originalLine The line number in original file + * @param integer $originalColumn The column number in original file + * @param string $sourceFile The original source file + */ + public function addMapping($generatedLine, $generatedColumn, $originalLine, $originalColumn, $fileInfo ){ + + $this->mappings[] = array( + 'generated_line' => $generatedLine, + 'generated_column' => $generatedColumn, + 'original_line' => $originalLine, + 'original_column' => $originalColumn, + 'source_file' => $fileInfo['currentUri'] + ); + + $this->sources[$fileInfo['currentUri']] = $fileInfo['filename']; + } + + + /** + * Generates the JSON source map + * + * @return string + * @see https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit# + */ + protected function generateJson(){ + + $sourceMap = array(); + $mappings = $this->generateMappings(); + + // File version (always the first entry in the object) and must be a positive integer. + $sourceMap['version'] = self::VERSION; + + + // An optional name of the generated code that this source map is associated with. + $file = $this->getOption('sourceMapFilename'); + if( $file ){ + $sourceMap['file'] = $file; + } + + + // An optional source root, useful for relocating source files on a server or removing repeated values in the 'sources' entry. This value is prepended to the individual entries in the 'source' field. + $root = $this->getOption('sourceRoot'); + if( $root ){ + $sourceMap['sourceRoot'] = $root; + } + + + // A list of original sources used by the 'mappings' entry. + $sourceMap['sources'] = array(); + foreach($this->sources as $source_uri => $source_filename){ + $sourceMap['sources'][] = $this->normalizeFilename($source_filename); + } + + + // A list of symbol names used by the 'mappings' entry. + $sourceMap['names'] = array(); + + // A string with the encoded mapping data. + $sourceMap['mappings'] = $mappings; + + if( $this->getOption('outputSourceFiles') ){ + // An optional list of source content, useful when the 'source' can't be hosted. + // The contents are listed in the same order as the sources above. + // 'null' may be used if some original sources should be retrieved by name. + $sourceMap['sourcesContent'] = $this->getSourcesContent(); + } + + // less.js compat fixes + if( count_if_countable($sourceMap['sources']) && empty($sourceMap['sourceRoot']) ){ + unset($sourceMap['sourceRoot']); + } + + return json_encode($sourceMap); + } + + /** + * Returns the sources contents + * + * @return array|null + */ + protected function getSourcesContent(){ + if(empty($this->sources)){ + return; + } + $content = array(); + foreach($this->sources as $sourceFile){ + $content[] = file_get_contents($sourceFile); + } + return $content; + } + + /** + * Generates the mappings string + * + * @return string + */ + public function generateMappings(){ + + if( !count_if_countable($this->mappings) ){ + return ''; + } + + $this->source_keys = array_flip(array_keys($this->sources)); + + + // group mappings by generated line number. + $groupedMap = $groupedMapEncoded = array(); + foreach($this->mappings as $m){ + $groupedMap[$m['generated_line']][] = $m; + } + ksort($groupedMap); + + $lastGeneratedLine = $lastOriginalIndex = $lastOriginalLine = $lastOriginalColumn = 0; + + foreach($groupedMap as $lineNumber => $line_map){ + while(++$lastGeneratedLine < $lineNumber){ + $groupedMapEncoded[] = ';'; + } + + $lineMapEncoded = array(); + $lastGeneratedColumn = 0; + + foreach($line_map as $m){ + $mapEncoded = $this->encoder->encode($m['generated_column'] - $lastGeneratedColumn); + $lastGeneratedColumn = $m['generated_column']; + + // find the index + if( $m['source_file'] ){ + $index = $this->findFileIndex($m['source_file']); + if( $index !== false ){ + $mapEncoded .= $this->encoder->encode($index - $lastOriginalIndex); + $lastOriginalIndex = $index; + + // lines are stored 0-based in SourceMap spec version 3 + $mapEncoded .= $this->encoder->encode($m['original_line'] - 1 - $lastOriginalLine); + $lastOriginalLine = $m['original_line'] - 1; + + $mapEncoded .= $this->encoder->encode($m['original_column'] - $lastOriginalColumn); + $lastOriginalColumn = $m['original_column']; + } + } + + $lineMapEncoded[] = $mapEncoded; + } + + $groupedMapEncoded[] = implode(',', $lineMapEncoded) . ';'; + } + + return rtrim(implode($groupedMapEncoded), ';'); + } + + /** + * Finds the index for the filename + * + * @param string $filename + * @return integer|false + */ + protected function findFileIndex($filename){ + return $this->source_keys[$filename]; + } + + /** + * fix windows paths + * @param string $path + * @return string + */ + public function fixWindowsPath($path, $addEndSlash = false){ + $slash = ($addEndSlash) ? '/' : ''; + if( !empty($path) ){ + $path = str_replace('\\', '/', $path); + $path = rtrim($path,'/') . $slash; + } + + return $path; + } + } diff --git a/model/Overview.php b/model/Overview.php index 8a467bc0..ac461f55 100644 --- a/model/Overview.php +++ b/model/Overview.php @@ -2,6 +2,8 @@ class Overview { + public $conference; + public function __construct(Conference $conference) { $this->conference = $conference; diff --git a/model/Room.php b/model/Room.php index 12b5a99c..c78afedd 100644 --- a/model/Room.php +++ b/model/Room.php @@ -50,12 +50,20 @@ public function getId() { } public function getSlug() { - return $this->slug; + if ($this->slug != NULL) { + return $this->slug; + } else { + return ""; + } } private function get($key, $fallbackValue = null) { $keychain = 'ROOMS.'.$this->getSlug().'.'.$key; - return $this->conference->get($keychain, $fallbackValue ?: @$GLOBALS['CONFIG']['ROOM_DEFAULTS'][$key]); + $fallback = null; + if (isset($GLOBALS['CONFIG']['ROOM_DEFAULTS'][$key])) { + $fallback = $GLOBALS['CONFIG']['ROOM_DEFAULTS'][$key]; + } + return $this->conference->get($keychain, $fallbackValue ?: $fallback); } private function has($key) { diff --git a/model/RoomSelection.php b/model/RoomSelection.php index 18a4738c..d091f945 100644 --- a/model/RoomSelection.php +++ b/model/RoomSelection.php @@ -2,6 +2,9 @@ class RoomSelection { + public $room; + public $selection; + public function __construct(Room $room, $selection) { $this->room = $room; diff --git a/model/RoomTab.php b/model/RoomTab.php index 4848f578..beead62a 100644 --- a/model/RoomTab.php +++ b/model/RoomTab.php @@ -2,6 +2,9 @@ class RoomTab { + public $room; + public $tab; + public function __construct(Room $room, $tab) { $this->room = $room; diff --git a/model/Schedule.php b/model/Schedule.php index afc70d4f..a95e2402 100644 --- a/model/Schedule.php +++ b/model/Schedule.php @@ -54,7 +54,8 @@ public function isOptout($event) { public function getMappedRoom($scheduleRoom) { $mapping = $this->getScheduleToRoomSlugMapping(); - return $this->getConference()->getRoomIfExists( @$mapping[$scheduleRoom] ); + $room = isset($mapping[$scheduleRoom]) ? $mapping[$scheduleRoom] : ""; + return $this->getConference()->getRoomIfExists( $room ); } public function getScheduleDisplayTime($basetime = null) @@ -68,12 +69,16 @@ public function getScheduleDisplayTime($basetime = null) private function fetchSchedule() { - $schedule = @file_get_contents($this->getScheduleCache()); - - if(!$schedule) + try { + $schedule = file_get_contents($this->getScheduleCache()); + + if(!$schedule) + return null; + + return simplexml_load_string($schedule); + } catch (ErrorException $e) { return null; - - return simplexml_load_string($schedule); + } } public function getRoomSchedule($roomName, $roomGuid) { diff --git a/model/Stream.php b/model/Stream.php index 4c20324e..a19c8cd2 100644 --- a/model/Stream.php +++ b/model/Stream.php @@ -2,6 +2,11 @@ class Stream { + public $room; + public $selection; + public $language; + public $translation_label; + public function __construct(Room $room, $selection, $language, $translation_label = null) { $this->room = $room; diff --git a/template/assemblies/feedback.phtml b/template/assemblies/feedback.phtml index 03630fe3..ebec3c4a 100644 --- a/template/assemblies/feedback.phtml +++ b/template/assemblies/feedback.phtml @@ -102,7 +102,7 @@
- +
diff --git a/template/assemblies/schedule.phtml b/template/assemblies/schedule.phtml index c80cb94d..2460cd53 100644 --- a/template/assemblies/schedule.phtml +++ b/template/assemblies/schedule.phtml @@ -25,8 +25,13 @@
+ + + + +
title="Switch to getDisplay())?>" - onmouseover="showEventDetails(event, {title:'', guid:'', url:'', type:''})" + onmouseover="showEventDetails(event, {title:'', guid:'', url:'', type:''})" >
- +

- + - +

@@ -70,7 +75,7 @@

- (no recording) + (no recording)

by 
diff --git a/template/overview.phtml b/template/overview.phtml index 3bbd832d..ba77989c 100644 --- a/template/overview.phtml +++ b/template/overview.phtml @@ -104,14 +104,15 @@ $upcoming = @$upcomingTalksPerRoom[ $room->getSlug() ] ?: []; // echo var_dump($upcoming); $current = @$upcoming['current']; - $next = @$upcoming['next']; ?> + $next = @$upcoming['next']; + $next_is_special = isset($next['special']) ? $next['special'] : false; ?>
Now (since ):
- +
Next ():
From dc57652519f248a2a7190990367f9eddc1add9cf Mon Sep 17 00:00:00 2001 From: Jannik Beyerstedt Date: Tue, 18 Jul 2023 22:28:38 +0200 Subject: [PATCH 2/2] PHP 8: Handle more errors explicitly The error control operator "@" has changed behavior in PHP8 and generally seems like a quite bad hack. So let's handle array/ dict access errors explicitly. --- config.php | 6 +++--- index.php | 11 ++++++----- lib/helper.php | 16 ++++++++++++++-- model/Conference.php | 2 +- model/ConferenceJson.php | 34 ++++++++++++++++++++-------------- model/Conferences.php | 5 +++-- model/Feedback.php | 3 ++- model/Schedule.php | 10 +++++++++- view/allclosed.php | 2 +- view/closed.php | 2 +- view/embed.php | 2 +- view/multiview.php | 2 +- 12 files changed, 62 insertions(+), 33 deletions(-) diff --git a/config.php b/config.php index 7c945423..5b00533a 100644 --- a/config.php +++ b/config.php @@ -24,11 +24,11 @@ * Protokollfreie URLs (welche, die mit // beginnen), werden automatisch mit dem korrekten Protokoll ergänzt. * In diesem Fall wird auch ein SSL-Umschalt-Button im Header angezeigt */ -if(@$_SERVER['SERVER_NAME'] == 'localhost' || @$_SERVER['SERVER_NAME'] == '0.0.0.0') +if(isset($_SERVER['SERVER_NAME']) && ($_SERVER['SERVER_NAME'] == 'localhost' || $_SERVER['SERVER_NAME'] == '0.0.0.0')) { // keine Konfiguration -> BASEURL wird automatisch erraten } -else if(@$_SERVER['SERVER_NAME'] == 'streaming.test.c3voc.de') +else if(isset($_SERVER['SERVER_NAME']) && ($_SERVER['SERVER_NAME'] == 'streaming.test.c3voc.de')) { $GLOBALS['CONFIG']['BASEURL'] = '//streaming.test.c3voc.de/'; } @@ -104,7 +104,7 @@ /** * Konfiguration der Room-Defaults * - * Falls in der Raum-Konfiguration innerhalb der Konferenz für diese Keys nichts definiert ist, + * Falls in der Raum-Konfiguration innerhalb der Konferenz für diese Keys nichts definiert ist, * fällt das System auf diese Werte zurück. */ diff --git a/index.php b/index.php index 2d5a5fd8..a53b9e0a 100644 --- a/index.php +++ b/index.php @@ -52,11 +52,11 @@ try { if(isset($_GET['htaccess'])) { - $route = @$_GET['route']; + $route = isset($_GET['route']) ? $_GET['route'] : ""; } elseif(isset($_SERVER["REQUEST_URI"])) { - $route = ltrim(@$_SERVER["REQUEST_URI"], '/'); + $route = ltrim($_SERVER["REQUEST_URI"], '/'); // serve static if($route != '' && file_exists($_SERVER["DOCUMENT_ROOT"].'/'.$route)) @@ -87,11 +87,12 @@ 'conference' => new GenericConference(), )); - if(isset($GLOBALS['CONFIG']['BASEURL']) && startswith('//', @$GLOBALS['CONFIG']['BASEURL'])) + if(isset($GLOBALS['CONFIG']['BASEURL']) && startswith('//', $GLOBALS['CONFIG']['BASEURL'])) { + $mandator = isset($GLOBALS['MANDATOR']) ? $GLOBALS['MANDATOR'] : ""; $tpl->set(array( - 'httpsurl' => forceslash(forceslash('https:'.$GLOBALS['CONFIG']['BASEURL']).@$GLOBALS['MANDATOR']).forceslash($route).url_params(), - 'httpurl' => forceslash(forceslash('http:'. $GLOBALS['CONFIG']['BASEURL']).@$GLOBALS['MANDATOR']).forceslash($route).url_params(), + 'httpsurl' => forceslash(forceslash('https:'.$GLOBALS['CONFIG']['BASEURL']).$mandator).forceslash($route).url_params(), + 'httpurl' => forceslash(forceslash('http:'. $GLOBALS['CONFIG']['BASEURL']).$mandator).forceslash($route).url_params(), )); } diff --git a/lib/helper.php b/lib/helper.php index 43c87481..b1c86672 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -244,8 +244,20 @@ function query_data($operation, $query, $variables = [], $assoc = false, $cache if (is_null($r)) { throw new NotFoundException(); } - + // TODO: add error handling? // TODO: should we return the cached value, when we did not get an answer? - return $assoc ? @$r['data'] : @$r->data; + if ($assoc) { + if (isset($r['data'])) { + return $r['data']; + } else { + throw new NotFoundException(); + } + } else { + if (isset($r->data)) { + return $r->data; + } else { + throw new NotFoundException(); + } + } } \ No newline at end of file diff --git a/model/Conference.php b/model/Conference.php index 971bccc4..41096408 100644 --- a/model/Conference.php +++ b/model/Conference.php @@ -20,7 +20,7 @@ public function getTitle() { } public function isPreviewEnabled() { - if(@$GLOBALS['forceopen']) + if(isset($GLOBALS['forceopen']) && $GLOBALS['forceopen']) return true; if($this->has('PREVIEW_DOMAIN') && ($this->get('PREVIEW_DOMAIN') == $_SERVER['SERVER_NAME'])) diff --git a/model/ConferenceJson.php b/model/ConferenceJson.php index 89678f6f..409207f9 100644 --- a/model/ConferenceJson.php +++ b/model/ConferenceJson.php @@ -12,26 +12,32 @@ public function __construct($json, $mandator) $c = $json->conference; $this->start = DateTime::createFromFormat(DateTimeInterface::ISO8601, $c->start); $this->end = DateTime::createFromFormat(DateTimeInterface::ISO8601, $c->end); - $this->html = @$c->streamingConfig->html ?: []; + $this->html = isset($c->streamingConfig->html) ? $c->streamingConfig->html : []; $this->rooms = []; - $rooms = (is_array(@$c->rooms) ? $c->rooms : @$c->rooms->nodes) ?: []; + if (isset($c->rooms)) { + if (is_array($c->rooms)) { + $rooms = $c->rooms; + } else { + $rooms = isset($c->rooms->nodes) ? $c->rooms->nodes : []; + } + } foreach($rooms as $r) { if (!$r) { continue; } $this->rooms[$r->slug] = array_merge( ['stream' => $r->streamId], - get_object_vars($r), - @get_object_vars($r->streamingConfig) ?: [], - @get_object_vars($r->streamingConfig->chat) ?: [] + get_object_vars($r), + (isset($r->streamingConfig) ? get_object_vars($r->streamingConfig) : []), + (isset($r->streamingConfig->chat) ? get_object_vars($r->streamingConfig->chat) : []) ); } $groups = []; if ( isset($c->streamingConfig->overviewPage->sections) ) { - foreach(@$c->streamingConfig->overviewPage->sections as $s) { - $groups[@$s->title] = array_map( + foreach($c->streamingConfig->overviewPage->sections as $s) { + $groups[$s->title] = array_map( function($r) { return $r->slug; }, @$s->items ?: @$s->rooms ?: [] ); @@ -44,15 +50,15 @@ function($r) { return $r->slug; }, $acronym = $mandator ?: $c->acronym; parent::__construct(array_merge( - @get_object_vars($c->streamingConfig) ?: [], - @get_object_vars($c->streamingConfig->features) ?: [], - @get_object_vars($c->streamingConfig->features->chat) ?: [], + isset($c->streamingConfig) ? get_object_vars($c->streamingConfig) : [], + isset($c->streamingConfig->features) ? get_object_vars($c->streamingConfig->features) : [], + isset($c->streamingConfig->features->chat) ? get_object_vars($c->streamingConfig->features->chat) : [], [ 'conference' => [ 'title' => $c->title, 'author' => $c->organizer, 'description' => $c->description, - 'keywords' => @implode(', ', $c->keywords), + 'keywords' => is_array($c->keywords) ? implode(', ', $c->keywords) : "", // future TODO: change structure "relive_json" => @$c->streamingConfig->features->relive !== false ? "https://cdn.c3voc.de/relive/".$acronym."/index.json" : null, "releases" => @$c->streamingConfig->features->releases !== false ? "https://media.ccc.de/c/".$acronym : null @@ -140,21 +146,21 @@ public function hasBannerHtml() { return !empty($this->html->banner); } public function getBannerHtml() { - return @$this->html->banner; + return isset($this->html->banner) ? $this->html->banner : ""; } public function hasFooterHtml() { return !empty($this->html->footer); } public function getFooterHtml() { - return @$this->html->footer; + return isset($this->html->footer) ? $this->html->footer : ""; } public function hasNotStartedHtml() { return !empty($this->html->not_started); } public function getNotStartedHtml() { - return @$this->html->not_started; + return isset($this->html->not_started) ? $this->html->not_started : ""; } } diff --git a/model/Conferences.php b/model/Conferences.php index 911b49cc..f2d06a00 100644 --- a/model/Conferences.php +++ b/model/Conferences.php @@ -65,7 +65,8 @@ public static function getFinishedConferencesSorted() { } public static function getLastConference() { - return @Conferences::getFinishedConferencesSorted()[0]; + $conferences = Conferences::getFinishedConferencesSorted(); + return isset($conferences[0]) ? $conferences[0] : null; } public static function exists($mandator) { @@ -133,7 +134,7 @@ public static function loadConferenceConfig($mandator) { } // config option for dynamic lookup feature defined below - if (!@$GLOBALS['CONFIG']['DYNAMIC_LOOKUP']) { + if (isset($GLOBALS['CONFIG']['DYNAMIC_LOOKUP']) && !$GLOBALS['CONFIG']['DYNAMIC_LOOKUP']) { throw new NotFoundException();; } diff --git a/model/Feedback.php b/model/Feedback.php index 7b603c94..fc154399 100644 --- a/model/Feedback.php +++ b/model/Feedback.php @@ -10,9 +10,10 @@ public function __construct(Conference $conference) } private function get($key) { + $global_feedback_elem = isset($GLOBALS['CONFIG']['FEEDBACK'][$key]) ? $GLOBALS['CONFIG']['FEEDBACK'][$key] : ""; return $this->conference->has(['FEEDBACK', $key]) ? $this->conference->get(['FEEDBACK', $key]) - : @$GLOBALS['CONFIG']['FEEDBACK'][$key]; + : $global_feedback_elem; } public function getConference() { diff --git a/model/Schedule.php b/model/Schedule.php index a95e2402..5b3465bc 100644 --- a/model/Schedule.php +++ b/model/Schedule.php @@ -364,7 +364,15 @@ public function getScheduleToRoomSlugMapping() $this->mapping = array(); foreach($this->getConference()->get('ROOMS') as $slug => $room) { - $key = @$room['name'] ?: @$room['SCHEDULE_NAME'] ?: @$room['DISPLAY'] ?: $slug; + // json has 'name', config.php has 'SCHEDULE_NAME' and 'DISPLAY' + $key = $slug; + if (isset($room['name'])) { + $key = $room['name']; + } elseif ($room['SCHEDULE_NAME']) { + $key = $room['SCHEDULE_NAME']; + } elseif ($room['DISPLAY']) { + $key = $room['DISPLAY']; + } $this->mapping[$key] = $slug; } } diff --git a/view/allclosed.php b/view/allclosed.php index 535e6e3a..a3f87fde 100644 --- a/view/allclosed.php +++ b/view/allclosed.php @@ -6,7 +6,7 @@ 'page' => 'allclosed', 'title' => 'See you soon … somewhere else!', - 'next' => @$events[0], + 'next' => isset($events[0]) ? $events[0] : null, 'events' => $events, 'last' => Conferences::getLastConference(), )); diff --git a/view/closed.php b/view/closed.php index 32a132e1..4ca0c449 100644 --- a/view/closed.php +++ b/view/closed.php @@ -6,6 +6,6 @@ 'page' => 'closed', 'title' => 'See you soon … somewhere else!', - 'next' => @$events[0], + 'next' => isset($events[0]) ? $events[0] : null, 'events' => $events, )); diff --git a/view/embed.php b/view/embed.php index 2071c3a1..c0e38f4d 100644 --- a/view/embed.php +++ b/view/embed.php @@ -28,5 +28,5 @@ 'room' => $room, 'stream' => $stream, - 'autoplay' => @$_GET['autoplay'], + 'autoplay' => isset($_GET['autoplay']) ? $_GET['autoplay'] : false, )); diff --git a/view/multiview.php b/view/multiview.php index 68259116..91011312 100644 --- a/view/multiview.php +++ b/view/multiview.php @@ -5,5 +5,5 @@ 'title' => 'Stream-Übersicht', 'rooms' => $conference->getRooms(), - 'selection' => @$_GET['selection'], + 'selection' => isset($_GET['selection']) ? $_GET['selection'] : "", ));