/** * Returns a Finder instance for the files that will be included in the * backup. * * By default we ignore unreadable files and directories as well as, common * version control folders / files, "Dot" files and anything matching the * exclude rules. * * @uses Finder * @return Finder The Finder iterator of all files to be included */ public function get_files() { $finder = new Finder(); $finder->followLinks(true); $finder->ignoreDotFiles(false); $finder->ignoreVCS(true); $finder->ignoreUnreadableDirs(true); // Skip unreadable files too $finder->filter(function (\SplFileInfo $file) { if (!$file->isReadable()) { return false; } }); // Finder expects exclude rules to be in a regex format $exclude_rules = $this->excludes->get_excludes_for_regex(); // Skips folders/files that match default exclude patterns foreach ($exclude_rules as $exclude) { $finder->notPath($exclude); } return $finder->in(Path::get_root()); }
/** * Recursively scans a directory to calculate the total filesize * * Locks should be set by the caller with `set_transient( 'hmbkp_directory_filesizes_running', true, HOUR_IN_SECONDS );` * * @return array $directory_sizes An array of directory paths => filesize sum of all files in directory */ public function recursive_filesize_scanner() { /** * Raise the `memory_limit` and `max_execution time` * * Respects the WP_MAX_MEMORY_LIMIT Constant and the `admin_memory_limit` * filter. */ @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT)); @set_time_limit(0); // Use the cached array directory sizes if available $directory_sizes = $this->get_cached_filesizes(); // If we do have it in cache then let's use it and also clear the lock if (is_array($directory_sizes)) { delete_transient('hmbkp_directory_filesizes_running'); return $directory_sizes; } // If we don't have it cached then we'll need to re-calculate $finder = new Finder(); $finder->followLinks(); $finder->ignoreDotFiles(false); $finder->ignoreUnreadableDirs(true); $files = $finder->in(Path::get_root()); foreach ($files as $file) { if ($file->isReadable()) { $directory_sizes[wp_normalize_path($file->getRealpath())] = $file->getSize(); } else { $directory_sizes[wp_normalize_path($file->getRealpath())] = 0; } } file_put_contents(PATH::get_path() . '/.files', gzcompress(json_encode($directory_sizes))); // Remove the lock delete_transient('hmbkp_directory_filesizes_running'); return $directory_sizes; }
/** * Simple class wrapper for Path::get_path() * * @return string */ private function get_path() { return Path::get_instance()->get_path(); }
/** * Convert the exclude rules to a format zip accepts * * @return string The exclude string ready to pass to `zip -x` */ public function get_exclude_string() { if (!$this->excludes) { return ''; } $excludes = $this->excludes->get_excludes(); foreach ($excludes as $key => &$rule) { $file = $absolute = $fragment = false; // Files don't end with / if (!in_array(substr($rule, -1), array('\\', '/'))) { $file = true; } elseif (in_array(substr($rule, 0, 1), array('\\', '/'))) { $absolute = true; } else { $fragment = true; } $rule = str_ireplace(Path::get_root(), '', untrailingslashit(wp_normalize_path($rule))); // Strip the preceeding slash if (in_array(substr($rule, 0, 1), array('\\', '/'))) { $rule = substr($rule, 1); } // Wrap directory fragments and files in wildcards for zip if ($fragment || $file) { $rule = '*' . $rule . '*'; } // Add a wildcard to the end of absolute url for zips if ($absolute) { $rule .= '*'; } } // Escape shell args for zip command $excludes = array_map('escapeshellarg', array_unique($excludes)); return implode(' -x ', $excludes); }