/** * @inheritDoc */ public function readLine() { if (!$this->file->eof()) { $line = $this->file->current(); $this->file->next(); return json_decode($line); } return false; }
/** * 返回文件从X行到Y行的内容(支持php5、php4) * @param String $filename 文件名 * @param integer $startLine 开始行 * @param integer $endLine 结束行 * @param string $method 方法 * @return array() 返回数组 */ function readFileByLines($filename, $startLine = 1, $endLine = 50, $method = 'rb') { $content = array(); $count = $endLine - $startLine; // 判断php版本(因为要用到SplFileObject,PHP>=5.1.0) if (version_compare(PHP_VERSION, '5.1.0', '>=')) { $fp = new SplFileObject($filename, $method); // 转到第N行, seek方法参数从0开始计数 $fp->seek($startLine - 1); for ($i = 0; $i <= $count; ++$i) { // current()获取当前行内容 $content[] = $fp->current(); // 下一行 $fp->next(); } } else { //PHP<5.1 $fp = fopen($filename, $method); if (!$fp) { return 'error:can not read file'; } // 跳过前$startLine行 for ($i = 1; $i < $startLine; ++$i) { fgets($fp); } // 读取文件行内容 for ($i; $i <= $endLine; ++$i) { $content[] = fgets($fp); } fclose($fp); } // array_filter过滤:false,null,'' return array_filter($content); }
/** * Get Code from file * @param $path * @param $line * @param $numLines * @return array|null */ private function getCode($path, $line, $numLines) { if (empty($path) || empty($line) || !file_exists($path)) { return NULL; } try { // Get the number of lines in the file $file = new \SplFileObject($path); $file->seek(PHP_INT_MAX); $totalLines = $file->key() + 1; // Work out which lines we should fetch $start = max($line - floor($numLines / 2), 1); $end = $start + ($numLines - 1); if ($end > $totalLines) { $end = $totalLines; $start = max($end - ($numLines - 1), 1); } // Get the code for this range $code = array(); $file->seek($start - 1); while ($file->key() < $end) { $code[$file->key() + 1] = rtrim($file->current()); $file->next(); } return $code; } catch (RuntimeException $ex) { return null; } }
protected function export($var, $return = false) { if ($var instanceof Closure) { /* dump anonymous function in to plain code.*/ $ref = new ReflectionFunction($var); $file = new SplFileObject($ref->getFileName()); $file->seek($ref->getStartLine() - 1); $result = ''; while ($file->key() < $ref->getEndLine()) { $result .= $file->current(); $file->next(); } $begin = strpos($result, 'function'); $end = strrpos($result, '}'); $result = substr($result, $begin, $end - $begin + 1); } elseif (is_object($var)) { /* dump object with construct function. */ $result = 'new ' . get_class($var) . '(' . $this->export(get_object_vars($var), true) . ')'; } elseif (is_array($var)) { /* dump array in plain array.*/ $array = array(); foreach ($var as $k => $v) { $array[] = var_export($k, true) . ' => ' . $this->export($v, true); } $result = 'array(' . implode(', ', $array) . ')'; } else { $result = var_export($var, true); } if (!$return) { print $result; } return $result; }
/** * Write the compiled csv to disk and return the file name * * @param array $sortedHeaders An array of sorted headers * * @return string The csv filename where the data was written */ public function prepare($cacheFile, $sortedHeaders) { $csvFile = $cacheFile . '.csv'; $handle = fopen($csvFile, 'w'); // Generate a csv version of the multi-row headers to write to disk $headerRows = [[], []]; foreach ($sortedHeaders as $idx => $header) { if (!is_array($header)) { $headerRows[0][] = $header; $headerRows[1][] = ''; } else { foreach ($header as $headerName => $subHeaders) { $headerRows[0][] = $headerName; $headerRows[1] = array_merge($headerRows[1], $subHeaders); if (count($subHeaders) > 1) { /** * We need to insert empty cells for the first row of headers to account for the second row * this acts as a faux horizontal cell merge in a csv file * | Header 1 | <---- 2 extra cells ----> | * | Sub 1 | Subheader 2 | Subheader 3 | */ $headerRows[0] = array_merge($headerRows[0], array_fill(0, count($subHeaders) - 1, '')); } } } } fputcsv($handle, $headerRows[0]); fputcsv($handle, $headerRows[1]); // TODO: Track memory usage $file = new \SplFileObject($cacheFile); while (!$file->eof()) { $csvRow = []; $row = json_decode($file->current(), true); if (!is_array($row)) { // Invalid json data -- don't process this row continue; } foreach ($sortedHeaders as $idx => $header) { if (!is_array($header)) { $csvRow[] = isset($row[$header]) ? $row[$header] : ''; } else { // Multi-row header, so we need to set all values $nestedHeaderName = array_keys($header)[0]; $nestedHeaders = $header[$nestedHeaderName]; foreach ($nestedHeaders as $nestedHeader) { $csvRow[] = isset($row[$nestedHeaderName][$nestedHeader]) ? $row[$nestedHeaderName][$nestedHeader] : ''; } } } fputcsv($handle, $csvRow); $file->next(); } $file = null; // Get rid of the file handle that SplFileObject has on cache file unlink($cacheFile); fclose($handle); return $csvFile; }
/** * @param \SplFileObject $stream * * Reads the file to parse its lines */ public function readFile(\SplFileObject $stream) { $stream->setFlags(\SplFileObject::READ_CSV | \SplFileObject::READ_AHEAD | \SplFileObject::SKIP_EMPTY | \SplFileObject::DROP_NEW_LINE); while (!$stream->eof()) { $this->parseLine($stream->current()); $stream->next(); } $stream = null; }
public function actionIndex() { Yii::import("application.models.*"); //get the latest idle cron job /* @var $latestidle JobQueue*/ $latestidle = JobQueue::model()->findByAttributes(array("status" => JobQueue::$JOBQUEUE_STATUS_IDLE)); if (!$latestidle) { echo "No file queued"; die; } //set status to on-going $latestidle->status = JobQueue::$JOBQUEUE_STATUS_ON_GOING; $latestidle->save(false); //retrieve file $queueFile = new SplFileObject($latestidle->filename); //read file $queueFile->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::DROP_NEW_LINE | SplFileObject::SKIP_EMPTY); $queueFile->next(); // Total_records , $queueFile->seek(PHP_INT_MAX); $linesTotal = $queueFile->key(); $latestidle->total_records = $linesTotal; $latestidle->save(false); $index = 0; foreach ($queueFile as $currentLine) { //iterate content if ($queueFile->key() === 0) { continue; } //TODO: processed_record $latestidle->processed_record = ++$index; $latestidle->save(false); $currentMobile = $currentLine[0]; $newBlackListedmobile = new BlackListedMobile(); //cleaning time $currentMobile = trim($currentMobile); $currentMobile = rtrim($currentMobile); $currentMobile = ltrim($currentMobile); $newBlackListedmobile->mobile_number = $currentMobile; $newBlackListedmobile->queue_id = $latestidle->queue_id; //set queueid if ($newBlackListedmobile->save()) { //save content echo "{$newBlackListedmobile->mobile_number} : Saved \n"; } else { echo "{$newBlackListedmobile->mobile_number} : Failed \n"; } } //when done //set status to done $latestidle->status = JobQueue::$JOBQUEUE_STATUS_DONE; $latestidle->date_done = date("Y-m-d H:i:s"); //set done datetime to now() $latestidle->save(); echo "Queue DONE \n"; }
public function rewind() { parent::rewind(); // If we are getting the first line as columns, take them then skip to // the next line. if ($this->_firstLineIsColumns) { $this->setColumns(parent::current()); parent::next(); } }
function generate($nb, $fixture = __DIR__ . '/fixtures/lorem.txt') { $lorems = new SplFileObject($fixture, 'a+'); $txt = ''; while ($nb > 0 && $lorems->valid()) { $txt .= $lorems->current(); $lorems->next(); $nb--; } return $txt; }
/** * @param $fileName * @param $page * @param $rows * @param string $methord * @return array */ public static function getContents($fileName, $page, $rows, $methord = 'rb') { $content = array(); $start = ($page - 1) * $rows; $fp = new \SplFileObject($fileName, $methord); $fp->seek($start); for ($i = 0; $i < $rows; ++$i) { $content[] = $fp->current(); $fp->next(); } return array_filter($content); }
public function getData() { try { $file = new SplFileObject($this->tmp_name, 'rb'); $data = null; for ($file; $file->valid(); $file->next()) { $data .= $file->current(); } return $data; } catch (RuntimeException $e) { } return null; }
public function testCheckAnswerTask3() { $this->assertFileExists('data/export.csv'); $filecsv = new \SplFileObject('data/export.csv'); $filecsv->setFlags(\SplFileObject::READ_CSV); $header = $filecsv->current(); $processor = new YieldProcessor(ReaderFactory::create('Db\\Product', include 'config/database.php'), WriterFactory::create('Stub'), function () { }); foreach ($processor->processing() as $item) { $filecsv->next(); $this->assertEquals($item, array_combine($header, $filecsv->current())); } }
/** * Move forward to next element */ public function next() { if (null === $this->_file) { $this->_openFile(); } if ($this->_file) { $this->_key = $this->_key + 1; if (!$this->_file->eof()) { $this->_file->next(); $this->_filepos = $this->_file->ftell(); } } }
public function testAgainstOriginalSedImplementation() { $tokenizer = new PennTreeBankTokenizer(); $tokenized = new \SplFileObject(TEST_DATA_DIR . "/Tokenizers/PennTreeBankTokenizerTest/tokenized"); $tokenized->setFlags(\SplFileObject::DROP_NEW_LINE); $sentences = new \SplFileObject(TEST_DATA_DIR . "/Tokenizers/PennTreeBankTokenizerTest/test.txt"); $sentences->setFlags(\SplFileObject::DROP_NEW_LINE); $tokenized->rewind(); foreach ($sentences as $sentence) { if ($sentence) { $this->assertEquals($tokenized->current(), implode(" ", $tokenizer->tokenize($sentence)), "Sentence: '{$sentence}' was not tokenized correctly"); } $tokenized->next(); } }
private function getClosureCode(\Closure $closure) { $reflection = new \ReflectionFunction($closure); // Open file and seek to the first line of the closure $file = new \SplFileObject($reflection->getFileName()); $file->seek($reflection->getStartLine() - 1); // Retrieve all of the lines that contain code for the closure $code = ''; while ($file->key() < $reflection->getEndLine()) { $line = $file->current(); $line = ltrim($line); $code .= $line; $file->next(); } return $code; }
function getMethodCode($name, $comment = false) { $fun = $this->getMethod($name); $start = $fun->getStartLine(); $end = $fun->getEndLine(); $fileName = $fun->getFileName(); $file = new SplFileObject($fileName); $file->seek($start - 1); $i = 0; $str = $comment ? $fun->getDocComment() : ''; while ($i++ < $end + 1 - $start) { $str .= $file->current(); $file->next(); } return $str; }
public static function setUpBeforeClass() { $reflection = new ReflectionClass(__NAMESPACE__ . '\\TestClass'); self::$startLine = $reflection->getStartLine(); self::$endLine = $reflection->getEndLine(); self::$testClassCode = NULL; /* GetCode as String */ $file = new \SplFileObject($reflection->getFileName()); $file->seek(self::$startLine - 1); while ($file->key() < $reflection->getEndLine()) { self::$testClassCode .= $file->current(); $file->next(); } self::$testClassCode = rtrim(self::$testClassCode, "\n"); unset($file); }
protected function _fetchCode() { // Open file and seek to the first line of the closure $file = new SplFileObject($this->reflection->getFileName()); $file->seek($this->reflection->getStartLine() - 1); // Retrieve all of the lines that contain code for the closure $code = ''; while ($file->key() < $this->reflection->getEndLine()) { $code .= $file->current(); $file->next(); } // Only keep the code defining that closure $begin = strpos($code, 'function'); $end = strrpos($code, '}'); $code = substr($code, $begin, $end - $begin + 1); return $code; }
/** * Move forward to next element */ public function next() { if (null === $this->_file) { $this->_openFile(); } if ($this->_file) { $this->_key = $this->_key + 1; while ($this->_file->valid()) { $this->_file->next(); $this->_filepos = $this->_file->ftell(); if ($this->_accept()) { $this->_valid = true; return; } } } $this->_valid = false; }
/** * 获取程序文件的文件头注释的标题 */ function getFileCommentTitle($filename, $startLine = 1, $endLine = 50, $method = 'rb') { $ret = ''; $count = $endLine - $startLine; $fp = new SplFileObject($filename, $method); $fp->seek($startLine - 1); // 转到第N行, seek方法参数从0开始计数 for ($i = 0; $i <= $count; ++$i) { $currLineStr = $fp->current(); // current()获取当前行内容 if (preg_match('/s?\\*s?([^\\*]{3,})/', $currLineStr, $matches)) { return $matches[1]; } $fp->next(); // 下一行 } return $ret; }
private function displaySource(\Exception $e) { $source = ''; $file = new \SplFileObject($e->getFile()); $lineNum = $e->getLine() - 4; if ($lineNum < 1) { $lineNum = 1; } $file->seek($lineNum); for ($l = 0; $l < 8; $l++) { if ($file->eof()) { break; } $source .= $file->current(); $file->next(); } return $source; }
/** * Evaluates the closure and the code in the reset of the file. This sets * the code for the closure, the namespace it is declared in (if any) and * any applicable namespace imports * @param ReflectionFunction The reflected function of the closure * @return String The code the closure runs */ private function evaluate(\ReflectionFunction $reflection) { $code = ''; $full = ''; $file = new \SplFileObject($reflection->getFileName()); while (!$file->eof()) { if ($file->key() >= $reflection->getStartLine() - 1 && $file->key() < $reflection->getEndLine()) { $code .= $file->current(); } $full .= $file->current(); $file->next(); } //@todo this assumes the function will be the only one on that line $begin = strpos($code, 'function'); //@todo this assumes the } will be the only one on that line $end = strrpos($code, '}'); $this->code = substr($code, $begin, $end - $begin + 1); $this->extractDetail($full); }
/** * Get's the next string of hook code to process. * * @return string */ public function getHook() { foreach ($this->hooks as $value) { $hook = '<?php function ' . $value[1] . '(){'; $reflection = new \ReflectionFunction($value[2]); $file = new \SplFileObject($reflection->getFileName()); $file->seek($reflection->getStartLine() - 1); $code = ''; while ($file->key() < $reflection->getEndLine()) { $code .= $file->current(); $file->next(); } $begin = strpos($code, 'function') + 8; $begin = strrpos($code, '{', $begin) + 1; $end = strrpos($code, '}'); $hook .= substr($code, $begin, $end - $begin); $hook .= '}' . PHP_EOL; (yield $value[0] => $hook); } }
/** * @param string $file * @param int $start * @param int $end * * @return string */ private function extractLines($file, $start, $end) { $fileObject = new \SplFileObject($file); $fileObject->seek($start - 1); $whitespaceLength = null; $content = ''; $iterator = $end - $start; while ($line = $fileObject->current()) { if ($whitespaceLength === null && preg_match('/^\\s*/', $line, $matches)) { $whitespaceLength = strlen($matches[0]); } $line = substr($line, $whitespaceLength); $content .= $line ?: PHP_EOL; $fileObject->next(); $iterator--; if ($iterator < 0) { break; } } return trim($content); }
function getFileLines($filename, $startLine = 1, $endLine = 50, $method = 'rb') { $content = array(); $count = $endLine - $startLine; $fp = new SplFileObject($filename, $method); $fp->seek($startLine - 1); // 转到第N行, seek方法参数从0开始计数 for ($i = 0; $i <= $count; ++$i) { $content[] = $fp->current(); // current()获取当前行内容 $fp->next(); // 下一行 } array_filter($content); // array_filter过滤:false,null,'' $str = ""; foreach ($content as $v) { $str .= $v . "\n"; } return $str; }
public function parseFile($logFile, &$startId, $finish = false) { if (!$logFile || !file_exists($logFile)) { return $this->setError('Log file error'); } try { $file = new SplFileObject($logFile); $file->seek(!$startId ? 0 : $startId - 1); $counter = 0; $items = array(); $item = null; while ($file->valid()) { $row = trim($file->current()); $file->next(); if (!$row) { continue; } $item = Mage::getModel('mpbackup/backup_progress_item')->parse($row, $item); $items[] = $item; $counter += $item->getLength(); if (!$finish && $counter > Mageplace_Backup_Helper_Const::BACKUP_PROCESS_REQUEST_PERIOD * Mageplace_Backup_Helper_Const::BACKUP_PROCESS_RESPONSE_SIZE) { break; } } $startId = $file->key(); } catch (Exception $e) { Mage::logException($e); return $this->setError($e->getMessage()); } if (empty($items)) { if ($finish) { return $this->setError('Log is empty (' . print_r($items, true) . ') and log process is finished'); } else { return $this->setData(self::TEXT, self::TEXT_TREE_POINT)->setError(print_r($items, true)); } } return $this->setData(self::ITEMS, $items); }
/** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has * expired, or if there was an error fetching it */ public function read($key) { $key = $this->_key($key); if (!$this->_init || $this->_setKey($key) === false) { return false; } if ($this->_config['lock']) { $this->_File->flock(LOCK_SH); } $this->_File->rewind(); $time = time(); $cachetime = (int) $this->_File->current(); if ($cachetime !== false && ($cachetime < $time || $time + $this->_config['duration'] < $cachetime)) { if ($this->_config['lock']) { $this->_File->flock(LOCK_UN); } return false; } $data = ''; $this->_File->next(); while ($this->_File->valid()) { $data .= $this->_File->current(); $this->_File->next(); } if ($this->_config['lock']) { $this->_File->flock(LOCK_UN); } $data = trim($data); if ($data !== '' && !empty($this->_config['serialize'])) { if ($this->_config['isWindows']) { $data = str_replace('\\\\\\\\', '\\', $data); } $data = unserialize((string) $data); } return $data; }
public function read($key) { if (!$this->is_init || $this->_openFile($key) === false) { return false; } if ($this->settings['lock']) { $this->file->flock(LOCK_SH); } $this->file->rewind(); $time = time(); $cachetime = intval($this->file->current()); //check for expiry if ($cachetime !== false && ($cachetime < $time || $time + $this->settings['cache_duration'] < $cachetime)) { if ($this->settings['lock']) { $this->file->flock(LOCK_UN); } return false; } $data = ''; $this->file->next(); while ($this->file->valid()) { $data .= $this->file->current(); $this->file->next(); } if ($this->settings['lock']) { $this->file->flock(LOCK_UN); } $data = trim($data); if ($data !== '' && !empty($this->settings['serialize'])) { if ($this->settings['is_windows']) { $data = str_replace('\\\\\\\\', '\\', $data); } $data = json_decode((string) $data, TRUE); } return $data; }
/** * create_generic() * * A function that creates an archive file * * The $excludes will be a list or relative path excludes if the $listmaker object is NULL otehrwise * will be absolute path excludes and relative path excludes can be had from the $listmaker object * * @param string $zip Full path & filename of ZIP Archive file to create * @param string $dir Full path of directory to add to ZIP Archive file * @parame array $excludes List of either absolute path exclusions or relative exclusions * @param string $tempdir [Optional] Full path of directory for temporary usage * @param object $listmaker The object from which we can get an inclusions list * @return bool True if the creation was successful, false otherwise * */ protected function create_generic($zip, $dir, $excludes, $tempdir, $listmaker) { $exitcode = 0; $output = array(); $zippath = ''; $command = ''; $temp_zip = ''; $excluding_additional = false; $exclude_count = 0; $exclusions = array(); $have_zip_errors = false; $zip_errors_count = 0; $zip_errors = array(); $have_zip_warnings = false; $zip_warnings_count = 0; $zip_warnings = array(); $have_zip_additions = false; $zip_additions_count = 0; $zip_additions = array(); $have_zip_debug = false; $zip_debug_count = 0; $zip_debug = array(); $have_zip_other = false; $zip_other_count = 0; $zip_other = array(); $zip_using_log_file = false; $logfile_name = ''; $zip_ignoring_symlinks = false; // The basedir must have a trailing directory separator $basedir = rtrim(trim($dir), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; if (empty($tempdir) || !@file_exists($tempdir)) { pb_backupbuddy::status('details', __('Temporary working directory must be available.', 'it-l10n-backupbuddy')); return false; } // Tell which zip version is being used $version = $this->get_zip_version(); if (true === is_array($version)) { 2 == $version['major'] && 0 == $version['minor'] ? $version['minor'] = 'X' : true; pb_backupbuddy::status('details', sprintf(__('Using zip version: %1$s.%2$s', 'it-l10n-backupbuddy'), $version['major'], $version['minor'])); } else { $version = array("major" => "X", "minor" => "Y"); pb_backupbuddy::status('details', sprintf(__('Using zip version: %1$s.%2$s', 'it-l10n-backupbuddy'), $version['major'], $version['minor'])); } // Get the command path for the zip command - should return a trimmed string $zippath = $this->get_command_path(self::COMMAND_ZIP_PATH); // Determine if we are using an absolute path if (!empty($zippath)) { pb_backupbuddy::status('details', __('Using absolute zip path: ', 'it-l10n-backupbuddy') . $zippath); } // Add the trailing slash if required $command = $this->slashify($zippath) . 'zip'; // Always do recursive operation $command .= ' -r'; // Check if the version of zip in use supports log file (which will help with memory usage for large sites) if (true === $this->get_zip_supports_log_file()) { // Choose to use log file so quieten stdout - we'll set up the log file later $command .= ' -q'; $zip_using_log_file = true; } // Check if we need to turn off compression by settings (faster but larger backup) if (true !== $this->get_compression()) { $command .= ' -0'; pb_backupbuddy::status('details', __('Zip archive creation compression disabled based on settings.', 'it-l10n-backupbuddy')); } else { pb_backupbuddy::status('details', __('Zip archive creation compression enabled based on settings.', 'it-l10n-backupbuddy')); } // Check if ignoring (not following) symlinks if (true === $this->get_ignore_symlinks()) { // Not all OS support this for command line zip but best to handle it late and just // indicate here it is requested but not supported by OS switch ($this->get_os_type()) { case self::OS_TYPE_NIX: // Want to not follow symlinks so set command option and set flag for later use $command .= ' -y'; $zip_ignoring_symlinks = true; pb_backupbuddy::status('details', __('Zip archive creation symbolic links will not be followed based on settings.', 'it-l10n-backupbuddy')); break; case self::OS_TYPE_WIN: pb_backupbuddy::status('details', __('Zip archive creation symbolic links requested to not be followed based on settings but this option is not supported on this operating system.', 'it-l10n-backupbuddy')); break; default: pb_backupbuddy::status('details', __('Zip archive creation symbolic links requested to not be followed based on settings but this option is not supported on this operating system.', 'it-l10n-backupbuddy')); } } else { pb_backupbuddy::status('details', __('Zip archive creation symbolic links will be followed based on settings.', 'it-l10n-backupbuddy')); } // Check if we are ignoring warnings - meaning can still get a backup even // if, e.g., some files cannot be read if (true === $this->get_ignore_warnings()) { // Note: warnings are being ignored but will still be gathered and logged pb_backupbuddy::status('details', __('Zip archive creation actionable warnings will be ignored based on settings.', 'it-l10n-backupbuddy')); } else { pb_backupbuddy::status('details', __('Zip archive creation actionable warnings will not be ignored based on settings.', 'it-l10n-backupbuddy')); } // Delete any existing zip file of same name - really this should never happen if (@file_exists($zip)) { pb_backupbuddy::status('details', __('Existing ZIP Archive file will be replaced.', 'it-l10n-backupbuddy')); @unlink($zip); } // Now we'll set up the logging to file if required - use full logging if (true === $zip_using_log_file) { $logfile_name = $tempdir . self::ZIP_LOG_FILE_NAME; $command .= " -lf '{$logfile_name}' -li"; } // Set temporary directory to store ZIP while it's being generated. $command .= " -b '{$tempdir}'"; // Specify where to place the finalized zip archive file // If warnings are being ignored we can tell zip to create the zip archive in the final // location - otherwise we must put it in a temporary location and move it later only // if there are no warnings. This copes with the case where (this) controlling script // gets timed out by the server and if the file were created in the final location with // warnings that should not be ignored we cannot prevent it being created. The -MM option // could be used but this prevents us catching such warnings and being able to report // them to the user in the case where the script hasn't been terminated. Additionally the // -MM option would bail out on the first encountered problem and so if there were a few // problems they would each not be found until the current one is fixed and try again. if (true === $this->get_ignore_warnings()) { $temp_zip = $zip; } else { $temp_zip = $tempdir . basename($zip); } $command .= " '{$temp_zip}' ."; // Now work out exclusions dependent on what we have been given if (is_object($listmaker) && (defined('USE_EXPERIMENTAL_ZIPBUDDY_INCLUSION') && true === USE_EXPERIMENTAL_ZIPBUDDY_INCLUSION)) { // We're doing an inclusion operation, but first we'll just show the exclusiosn // For zip we need relative rather than absolute exclusion spaths $exclusions = $listmaker->get_relative_excludes($basedir); if (count($exclusions) > 0) { pb_backupbuddy::status('details', __('Calculating directories to exclude from backup.', 'it-l10n-backupbuddy')); $excluding_additional = false; $exclude_count = 0; foreach ($exclusions as $exclude) { if (!strstr($exclude, 'backupbuddy_backups')) { // Set variable to show we are excluding additional directories besides backup dir. $excluding_additional = true; } pb_backupbuddy::status('details', __('Excluding', 'it-l10n-backupbuddy') . ': ' . $exclude); $exclude_count++; } } // Get the list of inclusions to process $inclusions = $listmaker->get_terminals(); // For each directory we need to put the "wildcard" on the end foreach ($inclusions as &$inclusion) { if (is_dir($inclusion)) { $inclusion .= DIRECTORY_SEPARATOR . "*"; } // Remove directory path prefix excluding leading slash to make relative (needed for zip) $inclusion = str_replace(rtrim($basedir, DIRECTORY_SEPARATOR), '', $inclusion); } // Now create the inclusions file in the tempdir // And update the command options $ifile = $tempdir . self::ZIP_INCLUSIONS_FILE_NAME; if (file_exists($ifile)) { @unlink($ifile); } file_put_contents($ifile, implode(PHP_EOL, $inclusions) . PHP_EOL . PHP_EOL); $command .= " -i@" . "'{$ifile}'"; } else { // We're doing an exclusion operation //$command .= "-i '*' "; // Not needed. Zip defaults to doing this. Removed July 10, 2012 for v3.0.41. // Since we had no $listmaker object or not using it get the standard relative excludes to process $exclusions = $excludes; if (count($exclusions) > 0) { // Handle exclusions by placing them in an exclusion text file. $exclusion_file = $tempdir . self::ZIP_EXCLUSIONS_FILE_NAME; $this->_render_exclusions_file($exclusion_file, $exclusions); pb_backupbuddy::status('details', sprintf(__('Using exclusion file `%1$s`', 'it-l10n-backupbuddy'), $exclusion_file)); $command .= ' -x@' . "'{$exclusion_file}'"; } } // If we can't use a log file but exec_dir isn't in use we can redirect stderr to stdout // If exec_dir is in use we cannot redirect because of command line escaping so cannot log errors/warnings if (false === $zip_using_log_file) { if (false === $this->get_exec_dir_flag()) { $command .= ' 2>&1'; } else { pb_backupbuddy::status('details', sprintf(__('Zip Errors/Warnings cannot not be logged with this version of zip and exec_dir active', 'it-l10n-backupbuddy'), true)); } } // Remember the current directory and change to the directory being added so that "." is valid in command $working_dir = getcwd(); chdir($dir); $command = self::OS_TYPE_WIN === $this->get_os_type() ? str_replace('\'', '"', $command) : $command; pb_backupbuddy::status('details', $this->get_method_tag() . __(' command', 'it-l10n-backupbuddy') . ': ' . $command); @exec($command, $output, $exitcode); // Set current working directory back to where we were chdir($working_dir); // Convenience for handling different scanarios $result = false; // If we used a log file then process the log file - else process output // Always scan the output/logfile for warnings, etc. and show warnings even if user has chosen to ignore them if (true === $zip_using_log_file) { try { $logfile = new SplFileObject($logfile_name, "rb"); while (!$logfile->eof()) { $line = $logfile->current(); $id = $logfile->key(); // Use the line number as unique key for later sorting $logfile->next(); if (preg_match('/^\\s*(zip warning:)/i', $line)) { // Looking for specific types of warning - in particular want the warning that // indicates a file couldn't be read as we want to treat that as a "skipped" // warning that indicates that zip flagged this as a potential problem but // created the zip file anyway - but it would have generated the non-zero exit // code of 18 and we key off that later. All other warnings are not considered // reasons to return a non-zero exit code whilst still creating a zip file so // we'll follow the lead on that and not have other warning types halt the backup. // So we'll try and look for a warning output that looks like it is file related... if (preg_match('/^\\s*(zip warning:)\\s*([^:]*:)\\s*(.*)/i', $line, $matches)) { // Matched to what looks like a file related warning so check particular cases switch (strtolower($matches[2])) { case "could not open for reading:": $zip_warnings[self::ZIP_WARNING_SKIPPED][$id] = trim($line); $zip_warnings_count++; break; case "name not matched:": $zip_other[self::ZIP_OTHER_GENERIC][$id] = trim($line); $zip_other_count++; break; default: $zip_warnings[self::ZIP_WARNING_GENERIC][$id] = trim($line); $zip_warnings_count++; } } else { // Didn't match to what would look like a file related warning so count it regardless $zip_warnings[self::ZIP_WARNING_GENERIC][$id] = trim($line); $zip_warnings_count++; } } elseif (preg_match('/^\\s*(zip error:)/i', $line)) { $zip_errors[$id] = trim($line); $zip_errors_count++; } elseif (preg_match('/^\\s*(adding:)/i', $line)) { // Currently not processing additions entried //$zip_additions[] = trim( $line ); //$zip_additions_count++; } elseif (preg_match('/^\\s*(sd:)/i', $line)) { $zip_debug[$id] = trim($line); $zip_debug_count++; } else { // Currently not processing other entries //$zip_other[] = trim( $line ); //$zip_other_count++; } } unset($logfile); @unlink($logfile_name); } catch (Exception $e) { // Something fishy - we should have been able to open the log file... $error_string = $e->getMessage(); pb_backupbuddy::status('details', sprintf(__('Log file could not be opened - error reported: %1$s', 'it-l10n-backupbuddy'), $error_string)); } } else { // TODO: $output could be large so if we parse it all into separate arrays then may want to shift // out each line and then discard it after copied to another array $id = 0; // Create a unique key (like a line number) for later sorting foreach ($output as $line) { if (preg_match('/^\\s*(zip warning:)/i', $line)) { // Looking for specific types of warning - in particular want the warning that // indicates a file couldn't be read as we want to treat that as a "skipped" // warning that indicates that zip flagged this as a potential problem but // created the zip file anyway - but it would have generated the non-zero exit // code of 18 and we key off that later. All other warnings are not considered // reasons to return a non-zero exit code whilst still creating a zip file so // we'll follow the lead on that and not have other warning types halt the backup. // So we'll try and look for a warning output that looks like it is file related... if (preg_match('/^\\s*(zip warning:)\\s*([^:]*:)\\s*(.*)/i', $line, $matches)) { // Matched to what looks like a file related warning so check particular cases switch (strtolower($matches[2])) { case "could not open for reading:": $zip_warnings[self::ZIP_WARNING_SKIPPED][$id++] = trim($line); $zip_warnings_count++; break; case "name not matched:": $zip_other[self::ZIP_OTHER_GENERIC][$id++] = trim($line); $zip_other_count++; break; default: $zip_warnings[self::ZIP_WARNING_GENERIC][$id++] = trim($line); $zip_warnings_count++; } } else { // Didn't match to what would look like a file related warning so count it regardless $zip_warnings[self::ZIP_WARNING_GENERIC][$id++] = trim($line); $zip_warnings_count++; } } elseif (preg_match('/^\\s*(zip error:)/i', $line)) { $zip_errors[$id++] = trim($line); $zip_errors_count++; } elseif (preg_match('/^\\s*(adding:)/i', $line)) { // Currently not processing additions entried //$zip_additions[] = trim( $line ); //$zip_additions_count++; $id++; } elseif (preg_match('/^\\s*(sd:)/i', $line)) { $zip_debug[$id++] = trim($line); $zip_debug_count++; } else { // Currently not processing other entries //$zip_other[] = trim( $line ); //$zip_other_count++; $id++; } } // Now free up the memory... unset($output); } // Set convenience flags $have_zip_warnings = 0 < $zip_warnings_count; $have_zip_errors = 0 < $zip_errors_count; $have_zip_additions = 0 < $zip_additions_count; $have_zip_debug = 0 < $zip_debug_count; $have_zip_other = 0 < $zip_other_count; // Always report the exit code regardless of whether we might ignore it or not pb_backupbuddy::status('details', __('Zip process exit code: ', 'it-l10n-backupbuddy') . $exitcode); // Always report the number of warnings - even just to confirm that we didn't have any pb_backupbuddy::status('details', sprintf(__('Zip process reported: %1$s warning%2$s', 'it-l10n-backupbuddy'), $zip_warnings_count, 1 == $zip_warnings_count ? '' : 's')); // Always report warnings regardless of whether user has selected to ignore them if (true === $have_zip_warnings) { $this->log_zip_reports($zip_warnings, self::$_warning_desc, "WARNING", self::MAX_WARNING_LINES_TO_SHOW, dirname(dirname($tempdir)) . DIRECTORY_SEPARATOR . 'pb_backupbuddy' . DIRECTORY_SEPARATOR . self::ZIP_WARNINGS_FILE_NAME); } // Always report other reports regardless if (true === $have_zip_other) { // Only report number of informationals if we have any as they are not that important pb_backupbuddy::status('details', sprintf(__('Zip process reported: %1$s information%2$s', 'it-l10n-backupbuddy'), $zip_other_count, 1 == $zip_other_count ? 'al' : 'als')); $this->log_zip_reports($zip_other, self::$_other_desc, "INFORMATION", self::MAX_OTHER_LINES_TO_SHOW, dirname(dirname($tempdir)) . DIRECTORY_SEPARATOR . 'pb_backupbuddy' . DIRECTORY_SEPARATOR . self::ZIP_OTHERS_FILE_NAME); } // See if we can figure out what happened - note that $exitcode could be non-zero for actionable warning(s) or error // if ( (no zip file) or (fatal exit code) or (not ignoring warnable exit code) ) // TODO: Handle condition testing with function calls based on mapping exit codes to exit type (fatal vs non-fatal) if (!@file_exists($temp_zip) || 0 != $exitcode && 18 != $exitcode || 18 == $exitcode && !$this->get_ignore_warnings()) { // If we have any zip errors reported show them regardless if (true === $have_zip_errors) { pb_backupbuddy::status('details', sprintf(__('Zip process reported: %1$s error%2$s', 'it-l10n-backupbuddy'), $zip_errors_count, 1 == $zip_errors_count ? '' : 's')); foreach ($zip_errors as $line) { pb_backupbuddy::status('details', __('Zip process reported: ', 'it-l10n-backupbuddy') . $line); } } // Report whether or not the zip file was created (whether that be in the final or temporary location) if (!@file_exists($temp_zip)) { pb_backupbuddy::status('details', __('Zip Archive file not created - check process exit code.', 'it-l10n-backupbuddy')); } else { pb_backupbuddy::status('details', __('Zip Archive file created but with errors/actionable-warnings so will be deleted - check process exit code and warnings.', 'it-l10n-backupbuddy')); } // The operation has failed one way or another. Note that as the user didn't choose to ignore errors the zip file // is always created in a temporary location and then only moved to final location on success without error or warnings. // Therefore if there is a zip file (produced but with warnings) it will not be visible and will be deleted when the // temporary directory is deleted below. $result = false; } else { // Got file with no error or warnings _or_ with warnings that the user has chosen to ignore if (false === $this->get_ignore_warnings()) { // Because not ignoring warnings the zip archive was built in temporary location so we need to move it pb_backupbuddy::status('details', __('Moving Zip Archive file to local archive directory.', 'it-l10n-backupbuddy')); // Make sure no stale file information clearstatcache(); @rename($temp_zip, $zip); if (@file_exists($zip)) { pb_backupbuddy::status('details', __('Zip Archive file moved to local archive directory.', 'it-l10n-backupbuddy')); pb_backupbuddy::status('message', __('Zip Archive file successfully created with no errors or actionable warnings.', 'it-l10n-backupbuddy')); $this->log_archive_file_stats($zip); $result = true; } else { pb_backupbuddy::status('details', __('Zip Archive file could not be moved to local archive directory.', 'it-l10n-backupbuddy')); $result = false; } } else { // Warnings were being ignored so built in final location so no need to move it if (@file_exists($zip)) { pb_backupbuddy::status('message', __('Zip Archive file successfully created with no errors (any actionable warnings ignored by user settings).', 'it-l10n-backupbuddy')); $this->log_archive_file_stats($zip); $result = true; } else { // Odd condition - file should be present but apparently not? pb_backupbuddy::status('details', __('Zip Archive file could not be found in local archive directory.', 'it-l10n-backupbuddy')); $result = false; } } } // Cleanup the temporary directory that will have all detritus and maybe incomplete zip file pb_backupbuddy::status('details', __('Removing temporary directory.', 'it-l10n-backupbuddy')); if (!$this->delete_directory_recursive($tempdir)) { pb_backupbuddy::status('details', __('Temporary directory could not be deleted: ', 'it-l10n-backupbuddy') . $tempdir); } return $result; }
private static function read_source_file($filename, $lineno, $context_lines = 5) { $frame = array('prefix' => array(), 'line' => '', 'suffix' => array(), 'filename' => $filename, 'lineno' => $lineno); if ($filename === null || $lineno === null) { return $frame; } // Code which is eval'ed have a modified filename.. Extract the // correct filename + linenumber from the string. $matches = array(); $matched = preg_match("/^(.*?)\\((\\d+)\\) : eval\\(\\)'d code\$/", $filename, $matches); if ($matched) { $frame['filename'] = $filename = $matches[1]; $frame['lineno'] = $lineno = $matches[2]; } // In the case of an anonymous function, the filename is sent as: // "</path/to/filename>(<lineno>) : runtime-created function" // Extract the correct filename + linenumber from the string. $matches = array(); $matched = preg_match("/^(.*?)\\((\\d+)\\) : runtime-created function\$/", $filename, $matches); if ($matched) { $frame['filename'] = $filename = $matches[1]; $frame['lineno'] = $lineno = $matches[2]; } try { $file = new SplFileObject($filename); $target = max(0, $lineno - ($context_lines + 1)); $file->seek($target); $cur_lineno = $target + 1; while (!$file->eof()) { $line = rtrim($file->current(), "\r\n"); if ($cur_lineno == $lineno) { $frame['line'] = $line; } elseif ($cur_lineno < $lineno) { $frame['prefix'][] = $line; } elseif ($cur_lineno > $lineno) { $frame['suffix'][] = $line; } $cur_lineno++; if ($cur_lineno > $lineno + $context_lines) { break; } $file->next(); } } catch (RuntimeException $exc) { return $frame; } return $frame; }