SeekquarrySeekquarry - Yioop Repo - Seekquarry

/ tests / LocaleModelTest.php⤓
<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\tests;

use seekquarry\yioop\configs as C;
use seekquarry\yioop\library as L;
use seekquarry\yioop\library\UnitTest;
use seekquarry\yioop\models\LocaleModel;

/**
 * LocaleModelTest checks how a site's locales sit over the locales that
 * ship with Yioop. The shipped strings and resources are in src/locale.
 * A site's folder of locales, the work directory's app/locale, holds only
 * the strings and resource files the site changed. Each case builds such
 * a site folder of its own under tests/test_files, so the work directory's own
 * locales are not touched.
 */
class LocaleModelTest extends UnitTest
{
    /**
     * CHANGED_ID names a string a site changed: seekquarry.com words its
     * activation request mail differently from the shipped string.
     */
    const CHANGED_ID = "register_controller_admin_activation_request";
    /**
     * SITE_WORDING is the site's own wording of the CHANGED_ID string.
     */
    const SITE_WORDING = "Seekquarry User Has Requested Activation";
    /**
     * $site_dir is the folder of locales a case writes, standing in for a
     * site's app/locale.
     * @var string
     */
    public $site_dir;
    /**
     * $locale_model is the LocaleModel each case works with.
     * @var LocaleModel
     */
    public $locale_model;
    /**
     * setUp makes an empty folder of locales for the case under
     * tests/test_files, with an en_US folder in it, and a LocaleModel.
     */
    public function setUp()
    {
        $this->site_dir = C\TEST_DIR . "/test_files/locale_test_" . getmypid();
        if (!is_dir($this->site_dir . "/en_US")) {
            mkdir($this->site_dir . "/en_US", 0777, true);
        }
        $this->locale_model = new LocaleModel();
    }
    /**
     * tearDown deletes the folder of locales setUp made.
     */
    public function tearDown()
    {
        $this->locale_model->db->unlinkRecursive($this->site_dir, true);
    }
    /**
     * siteCopyKeepsOnlyChangedStringsTestCase checks that rewriting a
     * site's configure.ini keeps only strings that differ from the
     * shipped ones. The site's file starts as an older copy of every
     * string, holding one it changed and one that equals the shipped one.
     * After updateLocale, only the changed string and the version line
     * are left, and reading the locale gives the site's wording for the
     * changed string and the shipped wording for the other.
     */
    public function siteCopyKeepsOnlyChangedStringsTestCase()
    {
        $shipped = L\parse_ini_with_fallback(C\FALLBACK_LOCALE_DIR .
            "/en_US/configure.ini")['strings'];
        $same_id = "view_locale_version";
        foreach ($shipped as $string_id => $value) {
            if ($value !== "" && $string_id != self::CHANGED_ID &&
                $string_id != "view_locale_version") {
                $same_id = $string_id;
                break;
            }
        }
        file_put_contents($this->site_dir . "/en_US/configure.ini",
            "[strings]\n" . self::CHANGED_ID . ' = "' . self::SITE_WORDING .
            "\"\n$same_id = \"" . addslashes($shipped[$same_id]) . "\"\n");
        $general_ini = L\parse_ini_with_fallback(C\FALLBACK_LOCALE_DIR .
            "/general.ini");
        $this->locale_model->updateLocale($general_ini,
            [self::CHANGED_ID, $same_id, "view_locale_version"],
            $this->site_dir, "en_US");
        $kept = L\parse_ini_with_fallback($this->site_dir .
            "/en_US/configure.ini")['strings'] ?? [];
        $this->assertEqual(array_keys($kept),
            [self::CHANGED_ID, "view_locale_version"],
            "only the changed string and the version line are kept");
        $read = L\localeConfigure("en_US", $this->site_dir)['strings'];
        $this->assertEqual($read[self::CHANGED_ID], self::SITE_WORDING,
            "the site's wording replaces the shipped one");
        $this->assertEqual($read[$same_id], $shipped[$same_id],
            "a string the site did not change is the shipped one");
    }
    /**
     * shippedCopiesAreRemovedTestCase checks removeShippedCopies on site
     * locale folders as earlier versions of Yioop left them. en_US has a
     * resources folder holding only a copy of the shipped locale.js, and
     * an old resources folder kept by an upgrade; both are deleted. de has
     * a resources folder holding a copy of its shipped locale.js and a
     * file the site made; that folder is left exactly as it is.
     */
    public function shippedCopiesAreRemovedTestCase()
    {
        $copied = $this->site_dir . "/en_US/resources";
        mkdir($copied);
        mkdir($this->site_dir . "/en_US/resources1700000000old");
        copy(C\FALLBACK_LOCALE_DIR . "/en_US/resources/locale.js",
            "$copied/locale.js");
        $changed = $this->site_dir . "/de/resources";
        mkdir($changed, 0777, true);
        copy(C\FALLBACK_LOCALE_DIR . "/de/resources/locale.js",
            "$changed/locale.js");
        file_put_contents("$changed/site_words.txt", "seekquarry\n");
        $this->locale_model->removeShippedCopies($this->site_dir);
        $this->assertFalse(is_dir($copied),
            "a resources folder of copies only is deleted");
        $this->assertFalse(is_dir($this->site_dir .
            "/en_US/resources1700000000old"), "the old folder is deleted");
        $this->assertEqual(array_values(array_diff(scandir($changed),
            [".", ".."])), ["locale.js", "site_words.txt"],
            "a resources folder holding a site's file is left as it is");
    }
    /**
     * shippedLocalesAreNeverWrittenTestCase asks updateLocale to save a
     * string into the locales that ship with Yioop, as a site with no
     * work directory once did. The shipped configure.ini must be left
     * with the same bytes.
     */
    public function shippedLocalesAreNeverWrittenTestCase()
    {
        $shipped_name = C\FALLBACK_LOCALE_DIR . "/en_US/configure.ini";
        $before = file_get_contents($shipped_name);
        $general_ini = L\parse_ini_with_fallback(C\FALLBACK_LOCALE_DIR .
            "/general.ini");
        $this->locale_model->updateLocale($general_ini, [self::CHANGED_ID],
            C\FALLBACK_LOCALE_DIR, "en_US",
            ["strings" => [self::CHANGED_ID => self::SITE_WORDING]]);
        $after = file_get_contents($shipped_name);
        if ($after !== $before) {
            file_put_contents($shipped_name, $before);
        }
        $this->assertTrue($after === $before,
            "the shipped configure.ini is unchanged");
    }
}