Skip to content

Command line tool for XML sync testing between languages: attributes #215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion configure.php
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ function getFileModificationHistory(): array {
$ac["TRANSLATION_ONLY_INCL_END"] = "-->";
}
checkvalue($ac['LANG']);
file_put_contents( __DIR__ . "/temp/lang" , $ac['LANG'] );

checking("whether the language is supported");
$LANGDIR = "{$ac['rootdir']}/{$ac['LANG']}";
Expand Down Expand Up @@ -798,8 +799,9 @@ function dom_saveload( DOMDocument $dom , string $filename = "" ) : string

if ( dom_load( $dom , "{$ac['srcdir']}/{$ac["INPUT_FILENAME"]}" ) )
{
echo "1 ";
dom_saveload( $dom ); // correct file/line/column on error messages
echo "done.\n";
echo "2 done.\n";
}
else
{
Expand Down
142 changes: 142 additions & 0 deletions scripts/translation/libqa/OutputBuffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php /*
+----------------------------------------------------------------------+
| Copyright (c) 1997-2025 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected], so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: André L F S Bacci <ae php.net> |
+----------------------------------------------------------------------+

# Description

This class caches formatted output, and calculates if this output is not
previously marked as ignored, before printing it. */

class OutputBuffer
{
private string $filename = "";
private string $header = "";
private array $matter = [];
private array $footer = [];

private OutputIgnore $ignore;
private string $options;

public function __construct( string $header , string $filename , OutputIgnore $ignore )
{
$filename = str_replace( "/./" , "/" , $filename );

$this->header = $header . ": " . $filename . "\n\n";
$this->filename = $filename;
$this->ignore = $ignore;

$copy = $ignore->residualArgv;
array_shift( $copy );
$this->options = implode( " " , $copy );
}

public function add( string $text )
{
$this->matter[] = $text;
}

public function addDiff( string $text , int $sourceCount , int $targetCount )
{
if ( $sourceCount == $targetCount )
return;
$prefix = "* ";
$suffix = " -{$targetCount} +{$sourceCount}";
if ( $sourceCount == 0 )
{
$prefix = "- ";
$suffix = $targetCount == 1 ? "" : " -{$targetCount}";
}
if ( $targetCount == 0 )
{
$prefix = "+ ";
$suffix = $sourceCount == 1 ? "" : " +{$sourceCount}";
}
$this->add( "{$prefix}{$text}{$suffix}\n" );
}

public function addFooter( string $text )
{
$this->footer[] = $text;
}

public function addLine()
{
if ( count( $this->matter ) > 0 && end( $this->matter ) != "\n" )
$this->add( "\n" );
}

public function print( bool $useAlternatePrinting = false )
{
if ( count( $this->matter ) == 0 && count( $this->footer ) == 0 )
return;

$hashHead = $this->hash( false );
$hashFull = $this->hash( true );

if ( $this->ignore->shouldIgnore( $this , $this->filename , $hashHead , $hashFull ) )
return;

print $this->header;

if ( $useAlternatePrinting )
$this->printMatterAlternate();
else
foreach( $this->matter as $text )
print $text;

if ( count( $this->matter ) )
print "\n";

foreach( $this->footer as $text )
print $text;

if ( count( $this->footer ) )
print "\n";
}

private function printMatterAlternate() : void
{
$add = array();
$del = array();
$rst = array();

foreach( $this->matter as $text )
{
if ( $text[0] == '+' ) $add[] = $text;
elseif ( $text[0] == '-' ) $del[] = $text;
else $rst[] = $text;
}

for ( $idx = 0 ; $idx < count( $this->matter ) ; $idx++ )
{
if ( isset( $add[ $idx ] ) ) print $add[ $idx ];
if ( isset( $del[ $idx ] ) ) print $del[ $idx ];
}

foreach( $rst as $text )
print $text;
}

private function hash( bool $withContents ) : string
{
$text = $this->header . $this->options;
if ( $withContents )
$text .= implode( "" , $this->matter );
$text = str_replace( " " , "" , $text );
$text = str_replace( "\n" , "" , $text );
$text = str_replace( "\r" , "" , $text );
$text = str_replace( "\t" , "" , $text );
return hash( "crc32b" , $text );
}
}
124 changes: 124 additions & 0 deletions scripts/translation/libqa/OutputIgnore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php /*
+----------------------------------------------------------------------+
| Copyright (c) 1997-2025 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected], so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: André L F S Bacci <ae php.net> |
+----------------------------------------------------------------------+

# Description

This class process commands for ignoring outputs, and complement non
ignored outputs with these commands. */

class OutputIgnore
{
public array $residualArgv;

private bool $appendIgnores = true;
private bool $showIgnore = true;
private string $filename = ".syncxml.ignores";
private string $argv0 = "";

public function __construct( array & $argv )
{
$this->argv0 = escapeshellarg( $argv[0] );

foreach( $argv as $key => $arg )
{
if ( str_starts_with( $arg , "--add-ignore=" ) )
{
$list = $this->loadIgnores();
$line = substr( $arg , 13 );
if ( ! in_array( $line , $list ) )
{
$list[] = $line;
$this->saveIgnores( $list );
}
exit;
}

if ( str_starts_with( $arg , "--del-ignore=" ) )
{
$list = $this->loadIgnores();
$line = substr( $arg , 13 );
$dels = 0;
while ( in_array( $line , $list ) )
{
$key = array_search( $line , $list );
unset( $list[$key] );
$dels++;
}
if ( $dels == 0 )
print "Ignore mark not found.\n";
else
$this->saveIgnores( $list );
exit;
}

if ( $arg == "--disable-ignore" )
{
$this->showIgnore = false;
unset( $argv[$key] );
}
}

$this->residualArgv = $argv;
}

private function loadIgnores()
{
if ( ! file_exists( $this->filename ) )
return [];
$data = file_get_contents( $this->filename );
return unserialize( gzdecode( $data ) );
}

public function saveIgnores( $data )
{
$contents = gzencode( serialize( $data ) );
file_put_contents( $this->filename , $contents );
}

public function shouldIgnore( OutputBuffer $output , string $filename , string $hashHeader , string $hashMatter )
{
$ret = false;

$prefix = "{$filename}:{$hashHeader}:";
$ignore = "{$filename}:{$hashHeader}:{$hashMatter}";
$marks = $this->loadIgnores();

// --add-ignore command

if ( in_array( $ignore , $marks ) )
$ret = true; // is already ignored
else //
if ( $this->showIgnore ) // show add command
$output->addFooter( " php {$this->argv0} --add-ignore=$ignore\n" );

// Remove valid ignores, leaves outdated ones for listing

while ( in_array( $ignore , $marks ) )
{
$key = array_search( $ignore , $marks );
unset( $marks[$key] );
}

// --del-ignore command

if ( $this->showIgnore ) // show del commands (for this file/prefix)
foreach ( $marks as $mark )
if ( $mark != null )
if ( str_starts_with( $mark , $prefix ) )
$output->addFooter( " php {$this->argv0} --del-ignore=$mark\n" );

return $ret;
}
}
27 changes: 27 additions & 0 deletions scripts/translation/libqa/SyncFileItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php /*
+----------------------------------------------------------------------+
| Copyright (c) 1997-2025 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected], so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: André L F S Bacci <ae php.net> |
+----------------------------------------------------------------------+

# Description

Holds file related data for synq XML tools. */

require_once __DIR__ . '/all.php';

class SyncFileItem
{
public string $sourceDir;
public string $targetDir;
public string $file;
}
65 changes: 65 additions & 0 deletions scripts/translation/libqa/SyncFileList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php /*
+----------------------------------------------------------------------+
| Copyright (c) 1997-2025 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected], so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: André L F S Bacci <ae php.net> |
+----------------------------------------------------------------------+

# Description

Generates (and caches) the list of files with TranslatedOk status. */

require_once __DIR__ . '/all.php';

class SyncFileList
{
static function load()
{
$file = __DIR__ . "/../../../temp/lang";
if ( ! file_exists( $file ) )
{
fwrite( STDERR , "Language file not found, run 'doc-base/configure.php'.\n" );
exit();
}

$lang = trim( file_get_contents( $file ) );
$cache = __DIR__ . "/../../../temp/$lang.oklist";

if ( file_exists( $cache ) )
{
$data = file_get_contents( $cache );
return unserialize( gzdecode( $data ) );
}

require_once __DIR__ . '/../lib/all.php';

$revcheck = new RevcheckRun( 'en' , $lang );
$revdata = $revcheck->revData;
$list = [];

foreach( $revdata->fileDetail as $file )
{
if ( $file->status != RevcheckStatus::TranslatedOk )
continue;

$item = new SyncFileItem();
$item->sourceDir = $revcheck->sourceDir;
$item->targetDir = $revcheck->targetDir;
$item->file = $file->path . '/' . $file->name;
$list[] = $item;
}

$contents = gzencode( serialize( $list ) );
file_put_contents( $cache , $contents );

return $list;
}
}
Loading
Loading