Each row is a JSON object * @param string $sourceFile * @param int $offset * @param int $limit * @param null|callable $formatter * @return array */ public static function readLogFile( string $sourceFile, int $offset = self::LOG_FILE_OFFSET, int $limit = self::LOG_FILE_LIMIT, $formatter = null ): array { $data = []; if(is_file($sourceFile)){ if(is_readable($sourceFile)){ $file = new ReverseSplFileObject($sourceFile, $offset); $file->setFlags(\SplFileObject::DROP_NEW_LINE | \SplFileObject::READ_AHEAD | \SplFileObject::SKIP_EMPTY); foreach( new \LimitIterator($file, 0, $limit) as $i => $rowData){ if( !empty($rowDataObj = (array)json_decode($rowData, true)) ){ if(is_callable($formatter)){ $formatter($rowDataObj); } $data[] = $rowDataObj; } } }else{ \Base::instance()->error(500, sprintf(self::ERROR_STREAM_READABLE, $sourceFile)); } } return $data; } /** * validate offset * @param int $offset * @return int */ public static function validateOffset(int $offset): int{ if( $offset < self::LOG_FILE_OFFSET_MIN || $offset > self::LOG_FILE_OFFSET_MAX ){ $offset = self::LOG_FILE_OFFSET; } return $offset; } /** * validate limit * @param int $limit * @return int */ public static function validateLimit(int $limit): int{ if( $limit < self::LOG_FILE_LIMIT_MIN || $limit > self::Log_File_LIMIT_MAX ){ $limit = self::LOG_FILE_LIMIT; } return $limit; } }