@param array $lines
@param int   $at
@param int   $lineNr
@param int   $linePos

@return string
7256
protected function getErrorDetail(array $lines, $at, &$lineNr, &$linePos)
    {
        $totalLength = 0;
        $lineNr      = 0;
        $linePos     = 0;
        $line        = '';

        foreach ($lines as $idx => $line) {
            $length = strlen($line);
            $totalLength += $length;

            if ($totalLength >= $at) {
                $lineNr  = 1 + $idx;
                $linePos = $length - ($totalLength - $at);
                break;
            }
        }

        $content = PHP_EOL . PHP_EOL . '<red>><reset> ' . $line . PHP_EOL
            . ' ' . ($linePos ? str_repeat(' ', $linePos) : '') . '<red>^<reset>' . PHP_EOL;

        return $content;
    }
936597
protected function parseDocBlock( $lines )
	{
		$data		= array();
		$descLines	= array();
		foreach( $lines as $line )
		{
			if( preg_match( $this->regexDocParam, $line, $matches ) )
			{
				$data['param'][$matches[4]]	= $this->parseDocParameter( $matches );
			}
			else if( preg_match( "@\*\s+\@return\s+(\w+)\s*(.+)?$@i", $line, $matches ) )
			{
				$data['return']	= $this->parseDocReturn( $matches );
			}
			else if( preg_match( "@\*\s+\@throws\s+(\w+)\s*(.+)?$@i", $line, $matches ) )
			{
				$data['throws'][]	= $this->parseDocThrows( $matches );
			}
			else if( preg_match( "@\*\s+\@trigger\s+(\w+)\s*(.+)?$@i", $line, $matches ) )
			{
				$data['trigger'][]	= $this->parseDocTrigger( $matches );
			}
			else if( preg_match( "@\*\s+\@author\s+(.+)\s*(<(.+)>)?$@iU", $line, $matches ) )
			{
				$author	= new ADT_PHP_Author( trim( $matches[1] ) );
				if( isset( $matches[3] ) )
					$author->setEmail( trim( $matches[3] ) );
				$data['author'][]	= $author;
			}
			else if( preg_match( "@\*\s+\@license\s+(\S+)( .+)?$@i", $line, $matches ) )
			{
				$data['license'][]	= $this->parseDocLicense( $matches );
			}
			else if( preg_match( "/^\*\s+@(\w+)\s*(.*)$/", $line, $matches ) )
			{
				switch( $matches[1] )
				{
					case 'implements':
					case 'deprecated':
					case 'todo':
					case 'copyright':
					case 'see':
					case 'uses':
					case 'link':
						$data[$matches[1]][]	= $matches[2];			
						break;
					case 'since':
					case 'version':
					case 'access':
					case 'category':
					case 'package':
					case 'subpackage':
						$data[$matches[1]]	= $matches[2];			
						break;
					default:
						break;
				}
			}
			else if( !$data && preg_match( "/^\*\s*([^@].+)?$/", $line, $matches ) )
				$descLines[]	= isset( $matches[1] ) ? trim( $matches[1] ) : "";
		}
		$data['description']	= trim( implode( "\n", $descLines ) );

		if( !isset( $data['throws'] ) )
			$data['throws']	= array();
		return $data;
	}
1021045
protected function getCodeSnippet($filePath, $lineNumber, $linesBefore = 3, $linesAfter = 3)
    {
        $lines = file($filePath);
        $offset = $lineNumber - $linesBefore - 1;
        $offset = max($offset, 0);
        $length = $linesAfter + $linesBefore + 1;
        $lines = array_slice($lines, $offset, $length, $preserveKeys = true);
        end($lines);
        $lineStrlen = strlen(key($lines) + 1);
        $snippet = '';

        foreach ($lines as $i => $line) {
            $snippet .= (abs($lineNumber) === $i + 1 ? '  > ' : '    ');
            $snippet .= str_pad($i + 1, $lineStrlen, ' ', STR_PAD_LEFT).'| '.rtrim($line).PHP_EOL;
        }

        return $snippet;
    }
348975
private static function logLineHasLogger($logger, $line)
    {
        if ($logger === null) {
            return true;
        }

        return array_key_exists('logger', $line) && $line['logger'] == $logger;
    }
1284618
public function appendLines($lines, $indent = 0)
    {
        foreach ($lines as $line) {
            $this->appendLine($line, $indent);
        }
    }
605856
private function getLineInfo($lines, $line, $i)
    {
        $currentLine = $line + $i;

        $index = $currentLine - 1;

        if (!array_key_exists($index, $lines)) {
            return;
        }
        return [
            'line' => '<span class="exception-currentline">' . $currentLine . '.</span> ' . SyntaxHighlight::process($lines[$index]),
            'wrap_left' => $i ? '' : '<span class="exception-line">', // color: #F5F5F5; background-color: #5A3E3E; width: 100%; display: block;
            'wrap_right' => $i ? '' : '</span>',
        ];
    }
947386
protected function parseAirlines(array $airlines)
    {
        $parsed = [];

        foreach ($airlines as $airline) {
            $parsed[$airline['fs']] = $airline;
        }

        return $parsed;
    }
1233703
private function parseMh(array $lines, $num, $start, $end)
    {
        return $this->parseSh($lines, $num, $start, $end);
    }
1367680
protected function unfold(array $lines)
    {
        $string = implode(PHP_EOL, $lines);
        $string = preg_replace('/' . PHP_EOL . '[ \t]/', '', $string);
        $lines  = explode(PHP_EOL, $string);

        return $lines;
    }
1150857
private function parseOutputLines(array $lines)
    {
        foreach ($lines as $line) {
            preg_match('/([MADRCU\? ])?([MADRCU\? ])?\ "?(\S+)"? ?( -> )?(\S+)?/', $line, $matches);
            $x = isset($matches[1]) ? $matches[1] : null;
            $y = isset($matches[2]) ? $matches[2] : null;
            $file = isset($matches[3]) ? $matches[3] : null;
            $renamedFile = isset($matches[4]) ? $matches[4] : null;
            $this->files[] = StatusFile::create($x, $y, $file, $renamedFile);
        }
    }
1100909
public function addRawFromAssocArray($lines, $indentation = 0)
	{
		foreach ($lines as $key => $value)
		{
			if (is_array($value))
			{
				$this->addLine($key . ': [', array("indentation"=>$indentation));
				$this->addRawFromAssocArray($value, $indentation + 1);
				$this->addLine(']', array("indentation"=>$indentation));
			}
			else
			{
				$this->addLine($key . ': ' . $value, array("indentation"=>$indentation));
			}
		}
	}
638354
protected function parseMessages($lines) {
    $messages = array();

    $message = array();
    foreach ($lines as $line) {
      if (empty($line) & !empty($message)) {
        $messages[] = $message;
        $message = array();
        continue;
      }
      $message[] = $line;
    }

    return $messages;
  }
656184
protected function wrapLines($lines, $indentationLevel = 0)
    {
        if ($wrapper = $this->getOption('wrapper')) {
            $lines = explode("\n", $lines);
            for ($i = 0; $i < count($lines); $i++) {
                // first line ignored
                if ($i === 0) {
                    continue;
                }
                $line = $lines[$i];
                if ($indentationLevel && $i < count($lines) - 1) {
                    $line = str_repeat($this->getOption('indentation'), $indentationLevel) . $line;
                }
                $lines[$i] = sprintf($wrapper, $line);
            }
            $lines = implode("\n", $lines);
        }

        return $lines;
    }
1241022
public function writeln($lines)
    {
        if (!is_array($lines)) {
            $lines = [$lines];
        }

        foreach ($lines as $line) {
            $this->write($line);
            $this->newline();
        }
        return $this;
    }
1222443
private function lineStartHandler(array $attrs): void
    {
        // Start horizontal position, current position (default)
        $x1 = ReportBaseElement::CURRENT_POSITION;
        if (isset($attrs['x1'])) {
            if ($attrs['x1'] === '0') {
                $x1 = 0;
            } elseif ($attrs['x1'] === '.') {
                $x1 = ReportBaseElement::CURRENT_POSITION;
            } elseif (!empty($attrs['x1'])) {
                $x1 = (float) $attrs['x1'];
            }
        }
        // Start vertical position, current position (default)
        $y1 = ReportBaseElement::CURRENT_POSITION;
        if (isset($attrs['y1'])) {
            if ($attrs['y1'] === '0') {
                $y1 = 0;
            } elseif ($attrs['y1'] === '.') {
                $y1 = ReportBaseElement::CURRENT_POSITION;
            } elseif (!empty($attrs['y1'])) {
                $y1 = (float) $attrs['y1'];
            }
        }
        // End horizontal position, maximum width (default)
        $x2 = ReportBaseElement::CURRENT_POSITION;
        if (isset($attrs['x2'])) {
            if ($attrs['x2'] === '0') {
                $x2 = 0;
            } elseif ($attrs['x2'] === '.') {
                $x2 = ReportBaseElement::CURRENT_POSITION;
            } elseif (!empty($attrs['x2'])) {
                $x2 = (float) $attrs['x2'];
            }
        }
        // End vertical position
        $y2 = ReportBaseElement::CURRENT_POSITION;
        if (isset($attrs['y2'])) {
            if ($attrs['y2'] === '0') {
                $y2 = 0;
            } elseif ($attrs['y2'] === '.') {
                $y2 = ReportBaseElement::CURRENT_POSITION;
            } elseif (!empty($attrs['y2'])) {
                $y2 = (float) $attrs['y2'];
            }
        }

        $line = $this->report_root->createLine($x1, $y1, $x2, $y2);
        $this->wt_report->addElement($line);
    }
160916
protected function initLines(array $lines)
    {
        $lines = $this->unfold($lines);

        if (stristr($lines[0], 'BEGIN:VCALENDAR') !== false) {
            $component = '';
            foreach ($lines as $line) {
                $line = rtrim($line); // Trim trailing whitespace
                $line = $this->removeUnprintableChars($line);

                if (!$this->disableCharacterReplacement) {
                    $line = $this->cleanData($line);
                }

                if ($this->replaceWindowsTimeZoneIds && strpos($line, 'TZID') !== false) {
                    $line = $this->replaceWindowsTimeZoneId($line);
                }

                $add = $this->keyValueFromString($line);

                $keyword = $add[0];
                $values  = $add[1]; // May be an array containing multiple values

                if (!is_array($values)) {
                    if (!empty($values)) {
                        $values = array($values); // Make an array as not already
                        $blankArray = array(); // Empty placeholder array
                        array_push($values, $blankArray);
                    } else {
                        $values = array(); // Use blank array to ignore this line
                    }
                } elseif (empty($values[0])) {
                    $values = array(); // Use blank array to ignore this line
                }

                // Reverse so that our array of properties is processed first
                $values = array_reverse($values);

                foreach ($values as $value) {
                    switch ($line) {
                        // https://www.kanzaki.com/docs/ical/vtodo.html
                        case 'BEGIN:VTODO':
                            if (!is_array($value)) {
                                $this->todoCount++;
                            }

                            $component = 'VTODO';
                            break;

                        // https://www.kanzaki.com/docs/ical/vevent.html
                        case 'BEGIN:VEVENT':
                            if (!is_array($value)) {
                                $this->eventCount++;
                            }

                            $component = 'VEVENT';
                            break;

                        // https://www.kanzaki.com/docs/ical/vfreebusy.html
                        case 'BEGIN:VFREEBUSY':
                            if (!is_array($value)) {
                                $this->freeBusyIndex++;
                            }

                            $component = 'VFREEBUSY';
                            break;

                        case 'BEGIN:VALARM':
                            if (!is_array($value)) {
                                $this->alarmCount++;
                            }

                            $component = 'VALARM';
                            break;

                        case 'END:VALARM':
                            $component = 'VEVENT';
                            break;

                        case 'BEGIN:DAYLIGHT':
                        case 'BEGIN:STANDARD':
                        case 'BEGIN:VCALENDAR':
                        case 'BEGIN:VTIMEZONE':
                            $component = $value;
                            break;

                        case 'END:DAYLIGHT':
                        case 'END:STANDARD':
                        case 'END:VCALENDAR':
                        case 'END:VFREEBUSY':
                        case 'END:VTIMEZONE':
                        case 'END:VTODO':
                            $component = 'VCALENDAR';
                            break;

                        case 'END:VEVENT':
                            if ($this->shouldFilterByWindow) {
                                $this->removeLastEventIfOutsideWindowAndNonRecurring();
                            }

                            $component = 'VCALENDAR';
                            break;

                        default:
                            $this->addCalendarComponentWithKeyAndValue($component, $keyword, $value);
                            break;
                    }
                }
            }

            $this->processEvents();

            if (!$this->skipRecurrence) {
                $this->processRecurrences();

                // Apply changes to altered recurrence instances
                if (!empty($this->alteredRecurrenceInstances)) {
                    $events = $this->cal['VEVENT'];

                    foreach ($this->alteredRecurrenceInstances as $alteredRecurrenceInstance) {
                        if (isset($alteredRecurrenceInstance['altered-event'])) {
                            $alteredEvent = $alteredRecurrenceInstance['altered-event'];
                            $key          = key($alteredEvent);
                            $events[$key] = $alteredEvent[$key];
                        }
                    }

                    $this->cal['VEVENT'] = $events;
                }
            }

            if ($this->shouldFilterByWindow) {
                $this->reduceEventsToMinMaxRange();
            }

            $this->processDateConversions();
        }
    }
159659
protected static function fixLastLine(array $lines, array $all): array
    {
        $last = end($all);
        $lastLine = end($lines);
        if ($lastLine !== false && $last !== $lastLine && rtrim($lastLine) === $last) {
            $lines[key($lines)] = $last;
        }
        return $lines;
    }