HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/ideasforum.kaunokolegija.lt/wp-content/plugins/loco-translate/src/gettext/Compiler.php
<?php
/**
 * Utility for compiling PO data to MO AND JSON files
 */
class Loco_gettext_Compiler {

    /**
     * @var Loco_api_WordPressFileSystem
     */
    private $fs;

    /**
     * @var Loco_fs_Siblings
     */
    private $files;

    /**
     * @var Loco_mvc_ViewParams
     */
    private $progress;

    /**
     * Construct with primary file (PO) being saved
     * @param Loco_fs_LocaleFile Localised PO file which may or may not exist yet
     */
    public function __construct( Loco_fs_LocaleFile $pofile ){
        $this->fs = new Loco_api_WordPressFileSystem;
        $this->files = new Loco_fs_Siblings($pofile);
        $this->progress = new Loco_mvc_ViewParams( array(
            'pobytes' => 0,
            'mobytes' => 0,
            'numjson' => 0,
        ) );
    }


    /**
     * @param Loco_gettext_Data
     * @param Loco_package_Project|null
     * @return self
     */
    public function writeAll( Loco_gettext_Data $po, Loco_package_Project $project = null ){
        $this->writePo($po);
        $this->writeMo($po);
        if( $project ){
            $this->writeJson($project,$po);
        }
        return $this;
    }


    /**
     * @param Loco_gettext_Data PO data
     * @return int bytes written to PO file
     * @throws Loco_error_WriteException
     */
    public function writePo( Loco_gettext_Data $po ){
        $file = $this->files->getSource();
        // Perform PO file backup before overwriting an existing PO
        if( $file->exists() ){
            $backups = new Loco_fs_Revisions($file);
            $backup = $backups->rotate($this->fs);
            // debug backup creation only under cli or ajax. too noisy printing on screen
            if( $backup && ( loco_doing_ajax() || 'cli' === PHP_SAPI ) && $backup->exists() ){
                Loco_error_AdminNotices::debug( sprintf('Wrote backup: %s -> %s',$file->basename(),$backup->basename() ) );
            }
        }
        $this->fs->authorizeSave($file);
        $bytes = $file->putContents( $po->msgcat() );
        $this->progress['pobytes'] = $bytes;
        return $bytes;
    }


    /**
     * @param Loco_gettext_Data PO data
     * @return int bytes written to MO file
     */
    public function writeMo( Loco_gettext_Data $po ){
        try {
            $file = $this->files->getBinary();
            $this->fs->authorizeSave($file);
            $bytes = $file->putContents( $po->msgfmt() );
            $this->progress['mobytes'] = $bytes;
        }
        catch( Exception $e ){
            Loco_error_AdminNotices::debug( $e->getMessage() );
            Loco_error_AdminNotices::warn( __('PO file saved, but MO file compilation failed','loco-translate') );
            $bytes = 0;
        }
        return $bytes;
    }


    /**
     * @param Loco_package_Project Translation set, required to resolve script paths
     * @param Loco_gettext_Data PO data to export
     * @return Loco_fs_FileList All json files created
     */
    public function writeJson( Loco_package_Project $project, Loco_gettext_Data $po ){
        $jsons = new Loco_fs_FileList;
        $pofile = $this->files->getSource();
        $base_dir = $project->getBundle()->getDirectoryPath();
        $domain = $project->getDomain()->getName();
        /* @var Loco_gettext_Data $fragment */
        foreach( $po->exportRefs('\\.js') as $ref => $fragment ){
            // Reference could be source js, or minified version.
            // Some build systems may differ, but WordPress only supports this. See WP-CLI MakeJsonCommand.
            if( substr($ref,-7) === '.min.js' ) {
                $min = $ref;
                $src = substr($ref,-7).'.js';
            }
            else {
                $src = $ref;
                $min = substr($ref,0,-3).'.min.js';
            }
            // Try both script paths to check whether deployed script actually exists
            $jsonfile = null;
            foreach( array($min,$src) as $relative ){
                $file = new Loco_fs_File($relative);
                $file->normalize($base_dir);
                if( $file->exists() ){
                    // Hook into load_script_textdomain_relative_path like load_script_textdomain() does.
                    $url = $project->getBundle()->getDirectoryUrl().$relative;
                    $relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $url );
                    if( ! is_string($relative) || '' === $relative ){
                        continue;
                    }
                    // Hashable reference is always finally unminified, as per load_script_textdomain()
                    if( substr($relative,-7) === '.min.js' ) {
                        $relative = substr($relative,0,-7).'.js';
                    }
                    $name = $pofile->filename().'-'.md5($relative).'.json';
                    $jsonfile = $pofile->cloneBasename($name);
                    $jsons->add( $jsonfile );
                    break;
                }
            }
            // if neither exists in the bundle, this is a source path that will never be resolved at runtime
            if( is_null($jsonfile) ){
                Loco_error_AdminNotices::debug( sprintf('Skipping JSON for %s; script not found in bundle',$ref) );
                continue;
            }
            // ok to write JED fragment to hashed JSON file
            try {
                $this->fs->authorizeSave($jsonfile);
                $jsonfile->putContents( $fragment->msgjed($domain,$ref) );
            }
            catch( Loco_error_WriteException $e ){
                Loco_error_AdminNotices::debug( $e->getMessage() );
                Loco_error_AdminNotices::warn( sprintf(__('JSON compilation failed for %s','loco-translate'),$ref));
            }
        }
        // clean up redundant JSONs including if no JSONs were compiled
        if( Loco_data_Settings::get()->jed_clean ){
            foreach( $this->files->getJsons() as $path ){
                $jsonfile = new Loco_fs_File($path);
                if( ! $jsons->has($jsonfile) ){
                    try {
                        $jsonfile->unlink();
                    }
                    catch( Loco_error_WriteException $e ){
                        Loco_error_AdminNotices::debug('Unable to remove redundant JSON: '.$e->getMessage() );
                    }
                }
            }
        }
        $this->progress['numjson'] = $jsons->count();
        return $jsons;
    }


    /**
     * Fetch compilation summary and raise most relevant success message
     * @return Loco_mvc_ViewParams
     */
    public function getSummary(){
        $pofile = $this->files->getSource();
        // Avoid calling this unless the initial PO save was successful
        if( ! $this->progress['pobytes'] || ! $pofile->exists() ){
            throw new LogicException('PO not saved');
        }
        // Summary for localised file includes MO+JSONs
        $mobytes = $this->progress['mobytes'];
        $numjson = $this->progress['numjson'];
        if( $mobytes && $numjson ){
            Loco_error_AdminNotices::success( __('PO file saved and MO/JSON files compiled','loco-translate') );
        }
        else if( $mobytes ){
            Loco_error_AdminNotices::success( __('PO file saved and MO file compiled','loco-translate') );
        }
        else {
            // translators: Where %s is either PO or POT
            Loco_error_AdminNotices::success( sprintf(__('%s file saved','loco-translate'),strtoupper($pofile->extension())) );
        }
        return $this->progress;
    }

}