183 lines
5.3 KiB
PHP
183 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Jfcherng\Diff;
|
|
|
|
use Jfcherng\Diff\Factory\RendererFactory;
|
|
use Jfcherng\Diff\Renderer\RendererConstant;
|
|
|
|
final class DiffHelper
|
|
{
|
|
/**
|
|
* The constructor.
|
|
*/
|
|
private function __construct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Get the absolute path of the project root directory.
|
|
*/
|
|
public static function getProjectDirectory(): string
|
|
{
|
|
static $path;
|
|
|
|
return $path ??= realpath(__DIR__ . '/..');
|
|
}
|
|
|
|
/**
|
|
* Get the information about available renderers.
|
|
*/
|
|
public static function getRenderersInfo(): array
|
|
{
|
|
static $info;
|
|
|
|
if (isset($info)) {
|
|
return $info;
|
|
}
|
|
|
|
$glob = implode(\DIRECTORY_SEPARATOR, [
|
|
self::getProjectDirectory(),
|
|
'src',
|
|
'Renderer',
|
|
'{' . implode(',', RendererConstant::RENDERER_TYPES) . '}',
|
|
'*.php',
|
|
]);
|
|
|
|
$fileNames = array_map(
|
|
// get basename without file extension
|
|
static fn (string $file): string => pathinfo($file, \PATHINFO_FILENAME),
|
|
// paths of all Renderer files
|
|
glob($glob, \GLOB_BRACE),
|
|
);
|
|
|
|
$renderers = array_filter(
|
|
$fileNames,
|
|
// only normal class files are wanted
|
|
static fn (string $fileName): bool => (
|
|
substr($fileName, 0, 8) !== 'Abstract'
|
|
&& substr($fileName, -9) !== 'Interface'
|
|
&& substr($fileName, -5) !== 'Trait'
|
|
),
|
|
);
|
|
|
|
$info = [];
|
|
foreach ($renderers as $renderer) {
|
|
$info[$renderer] = RendererFactory::resolveRenderer($renderer)::INFO;
|
|
}
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* Get the available renderers.
|
|
*
|
|
* @return string[] the available renderers
|
|
*/
|
|
public static function getAvailableRenderers(): array
|
|
{
|
|
return array_keys(self::getRenderersInfo());
|
|
}
|
|
|
|
/**
|
|
* Get the content of the CSS style sheet for HTML renderers.
|
|
*
|
|
* @throws \LogicException path is a directory
|
|
* @throws \RuntimeException path cannot be opened
|
|
*/
|
|
public static function getStyleSheet(): string
|
|
{
|
|
static $fileContent;
|
|
|
|
if (isset($fileContent)) {
|
|
return $fileContent;
|
|
}
|
|
|
|
$filePath = self::getProjectDirectory() . '/example/diff-table.css';
|
|
|
|
$file = new \SplFileObject($filePath, 'r');
|
|
|
|
return $fileContent = $file->fread($file->getSize());
|
|
}
|
|
|
|
/**
|
|
* Gets the diff statistics such as inserted and deleted etc...
|
|
*
|
|
* @return array<string,float> the statistics
|
|
*/
|
|
public static function getStatistics(): array
|
|
{
|
|
return Differ::getInstance()->getStatistics();
|
|
}
|
|
|
|
/**
|
|
* All-in-one static method to calculate the diff between two strings (or arrays of strings).
|
|
*
|
|
* @param string|string[] $old the old string (or array of lines)
|
|
* @param string|string[] $new the new string (or array of lines)
|
|
* @param string $renderer the renderer name
|
|
* @param array $differOptions the options for Differ object
|
|
* @param array $rendererOptions the options for renderer object
|
|
*
|
|
* @return string the rendered differences
|
|
*/
|
|
public static function calculate(
|
|
$old,
|
|
$new,
|
|
string $renderer = 'Unified',
|
|
array $differOptions = [],
|
|
array $rendererOptions = []
|
|
): string {
|
|
// always convert into array form
|
|
\is_string($old) && ($old = explode("\n", $old));
|
|
\is_string($new) && ($new = explode("\n", $new));
|
|
|
|
return RendererFactory::getInstance($renderer)
|
|
->setOptions($rendererOptions)
|
|
->render(
|
|
Differ::getInstance()
|
|
->setOldNew($old, $new)
|
|
->setOptions($differOptions),
|
|
)
|
|
;
|
|
}
|
|
|
|
/**
|
|
* All-in-one static method to calculate the diff between two files.
|
|
*
|
|
* @param string $old the path of the old file
|
|
* @param string $new the path of the new file
|
|
* @param string $renderer the renderer name
|
|
* @param array $differOptions the options for Differ object
|
|
* @param array $rendererOptions the options for renderer object
|
|
*
|
|
* @throws \LogicException path is a directory
|
|
* @throws \RuntimeException path cannot be opened
|
|
*
|
|
* @return string the rendered differences
|
|
*/
|
|
public static function calculateFiles(
|
|
string $old,
|
|
string $new,
|
|
string $renderer = 'Unified',
|
|
array $differOptions = [],
|
|
array $rendererOptions = []
|
|
): string {
|
|
// we want to leave the line-ending problem to static::calculate()
|
|
// so do not set SplFileObject::DROP_NEW_LINE flag
|
|
// otherwise, we will lose \r if the line-ending is \r\n
|
|
$oldFile = new \SplFileObject($old, 'r');
|
|
$newFile = new \SplFileObject($new, 'r');
|
|
|
|
return self::calculate(
|
|
// fread() requires the length > 0 hence we plus 1 for empty files
|
|
$oldFile->fread($oldFile->getSize() + 1),
|
|
$newFile->fread($newFile->getSize() + 1),
|
|
$renderer,
|
|
$differOptions,
|
|
$rendererOptions,
|
|
);
|
|
}
|
|
}
|