first commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
use WPML\ST\TranslationFile\StringEntity;
|
||||
|
||||
class Builder extends \WPML\ST\TranslationFile\Builder {
|
||||
|
||||
/** @var Generator */
|
||||
private $generator;
|
||||
|
||||
public function __construct( Generator $generator ) {
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StringEntity[] $strings
|
||||
* @return string
|
||||
*/
|
||||
public function get_content( array $strings ) {
|
||||
return $this->generator->getContent( $strings );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
use WP_Filesystem_Direct;
|
||||
use WPML\ST\MO\Generate\Process\Status;
|
||||
use WPML\ST\MO\Generate\Process\SingleSiteProcess;
|
||||
use WPML\ST\MO\Notice\RegenerationInProgressNotice;
|
||||
use function wpml_get_admin_notices;
|
||||
|
||||
class FailureHooks implements \IWPML_Backend_Action {
|
||||
use makeDir;
|
||||
|
||||
const NOTICE_GROUP = 'mo-failure';
|
||||
const NOTICE_ID_MISSING_FOLDER = 'missing-folder';
|
||||
|
||||
/** @var Status */
|
||||
private $status;
|
||||
|
||||
/** @var SingleSiteProcess $singleProcess */
|
||||
private $singleProcess;
|
||||
|
||||
public function __construct(
|
||||
WP_Filesystem_Direct $filesystem,
|
||||
Status $status,
|
||||
SingleSiteProcess $singleProcess
|
||||
) {
|
||||
$this->filesystem = $filesystem;
|
||||
$this->status = $status;
|
||||
$this->singleProcess = $singleProcess;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'admin_init', [ $this, 'checkDirectories' ] );
|
||||
}
|
||||
|
||||
public function checkDirectories() {
|
||||
if ( $this->isDirectoryMissing( WP_LANG_DIR ) ) {
|
||||
$this->resetRegenerateStatus();
|
||||
$this->displayMissingFolderNotice( WP_LANG_DIR );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $this->isDirectoryMissing( self::getSubdir() ) ) {
|
||||
$this->resetRegenerateStatus();
|
||||
|
||||
if ( ! $this->maybeCreateSubdir() ) {
|
||||
$this->displayMissingFolderNotice( self::getSubdir() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->status->isComplete() ) {
|
||||
$this->displayRegenerateInProgressNotice();
|
||||
$this->singleProcess->runPage();
|
||||
}
|
||||
|
||||
if ( $this->status->isComplete() ) {
|
||||
wpml_get_admin_notices()->remove_notice( RegenerationInProgressNotice::GROUP, RegenerationInProgressNotice::ID );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*/
|
||||
public function displayMissingFolderNotice( $dir ) {
|
||||
$notices = wpml_get_admin_notices();
|
||||
$notice = $notices->get_new_notice(
|
||||
self::NOTICE_ID_MISSING_FOLDER, self::missingFolderNoticeContent( $dir ),
|
||||
self::NOTICE_GROUP
|
||||
);
|
||||
$notice->set_css_classes( 'error' );
|
||||
$notices->add_notice( $notice );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function missingFolderNoticeContent( $dir ) {
|
||||
$text = '<p>' .
|
||||
esc_html__( 'WPML String Translation is attempting to write .mo files with translations to folder:',
|
||||
'wpml-string-translation' ) . '<br/>' .
|
||||
str_replace( '\\', '/', $dir ) .
|
||||
'</p>';
|
||||
|
||||
$text .= '<p>' . esc_html__( 'This folder appears to be not writable. This is blocking translation for strings from appearing on the site.',
|
||||
'wpml-string-translation' ) . '</p>';
|
||||
|
||||
$text .= '<p>' . esc_html__( 'To resolve this, please contact your hosting company and request that they make that folder writable.',
|
||||
'wpml-string-translation' ) . '</p>';
|
||||
|
||||
$url = 'https://wpml.org/faq/cannot-write-mo-files/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmlst';
|
||||
$link = '<a href="' . $url . '" target="_blank" rel="noreferrer noopener" >' .
|
||||
esc_html__( "WPML's documentation on troubleshooting .mo files generation.",
|
||||
'wpml-string-translation' ) .
|
||||
'</a>';
|
||||
|
||||
$text .= '<p>' . sprintf( esc_html__( 'For more details, see %s.', 'wpml-string-translation' ),
|
||||
$link ) . '</p>';
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
private function displayRegenerateInProgressNotice() {
|
||||
$notices = wpml_get_admin_notices();
|
||||
$notices->remove_notice( self::NOTICE_GROUP, self::NOTICE_ID_MISSING_FOLDER );
|
||||
$notices->add_notice( new RegenerationInProgressNotice() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function getSubdir() {
|
||||
return WP_LANG_DIR . '/' . \WPML\ST\TranslationFile\Manager::SUB_DIRECTORY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isDirectoryMissing( $dir ) {
|
||||
return ! $this->filesystem->is_writable( $dir );
|
||||
}
|
||||
|
||||
private function resetRegenerateStatus() {
|
||||
$this->status->markIncomplete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
|
||||
use SitePress;
|
||||
use WPML\ST\MO\Generate\Process\ProcessFactory;
|
||||
use function WPML\Container\make;
|
||||
use WPML\ST\MO\Scan\UI\Factory as UiFactory;
|
||||
|
||||
class FailureHooksFactory implements \IWPML_Backend_Action_Loader {
|
||||
/**
|
||||
* @return FailureHooks|null
|
||||
* @throws \WPML\Auryn\InjectionException
|
||||
*/
|
||||
public function create() {
|
||||
/** @var SitePress $sitepress */
|
||||
global $sitepress;
|
||||
|
||||
if ( $sitepress->is_setup_complete() && $this->hasRanPreGenerateViaUi() ) {
|
||||
$inBackground = true;
|
||||
|
||||
return make( FailureHooks::class, [
|
||||
':status' => ProcessFactory::createStatus( $inBackground ),
|
||||
':singleProcess' => ProcessFactory::createSingle( $inBackground ),
|
||||
] );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws \WPML\Auryn\InjectionException
|
||||
*/
|
||||
private function hasRanPreGenerateViaUi() {
|
||||
$uiPreGenerateStatus = ProcessFactory::createStatus( false );
|
||||
|
||||
return $uiPreGenerateStatus->isComplete()
|
||||
|| UiFactory::isDismissed()
|
||||
|| ! ProcessFactory::createSingle()->getPagesCount();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\ST\TranslateWpmlString;
|
||||
use WPML\ST\TranslationFile\StringEntity;
|
||||
use function wpml_collect;
|
||||
|
||||
class Generator {
|
||||
/** @var MOFactory */
|
||||
private $moFactory;
|
||||
|
||||
public function __construct( MOFactory $moFactory ) {
|
||||
$this->moFactory = $moFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StringEntity[] $entries
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent( array $entries ) {
|
||||
$mo = $this->moFactory->createNewInstance();
|
||||
wpml_collect( $entries )
|
||||
->reduce( [ $this, 'createMOFormatEntities' ], wpml_collect( [] ) )
|
||||
->filter( function( array $entry ) { return ! empty($entry['singular']); } )
|
||||
->each( [ $mo, 'add_entry' ] );
|
||||
|
||||
$mem_file = fopen( 'php://memory', 'r+' );
|
||||
$mo->export_to_file_handle( $mem_file );
|
||||
|
||||
rewind( $mem_file );
|
||||
$mo_content = stream_get_contents( $mem_file );
|
||||
|
||||
fclose( $mem_file );
|
||||
|
||||
return $mo_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $carry
|
||||
* @param StringEntity $entry
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function createMOFormatEntities( $carry, StringEntity $entry ) {
|
||||
$carry->push( $this->mapStringEntityToMOFormatUsing( $entry, 'original' ) );
|
||||
|
||||
if ( TranslateWpmlString::canTranslateWithMO( $entry->get_original(), $entry->get_name() ) ) {
|
||||
$carry->push( $this->mapStringEntityToMOFormatUsing( $entry, 'name' ) );
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StringEntity $entry
|
||||
* @param string $singularField
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mapStringEntityToMOFormatUsing( StringEntity $entry, $singularField ) {
|
||||
return [
|
||||
'singular' => $entry->{'get_' . $singularField}(),
|
||||
'translations' => $entry->get_translations(),
|
||||
'context' => $entry->get_context(),
|
||||
'plural' => $entry->get_original_plural(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
class MOFactory {
|
||||
/**
|
||||
* @return \MO
|
||||
*/
|
||||
public function createNewInstance() {
|
||||
return new \MO();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
use GlobIterator;
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\ST\TranslationFile\Domains;
|
||||
use WPML\ST\TranslationFile\StringsRetrieve;
|
||||
use WPML_Language_Records;
|
||||
|
||||
class Manager extends \WPML\ST\TranslationFile\Manager {
|
||||
|
||||
public function __construct(
|
||||
StringsRetrieve $strings,
|
||||
Builder $builder,
|
||||
\WP_Filesystem_Direct $filesystem,
|
||||
WPML_Language_Records $language_records,
|
||||
Domains $domains
|
||||
) {
|
||||
parent::__construct( $strings, $builder, $filesystem, $language_records, $domains );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getFileExtension() {
|
||||
return 'mo';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPartialFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
protected function getDomains() {
|
||||
return $this->domains->getMODomains();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasFiles() {
|
||||
return (bool) ( new GlobIterator( self::getSubdir() . '/*.mo' ) )->count();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
use function WPML\Container\make;
|
||||
|
||||
class ManagerFactory {
|
||||
|
||||
/**
|
||||
* @return Manager
|
||||
* @throws \WPML\Auryn\InjectionException
|
||||
*/
|
||||
public static function create() {
|
||||
return make( Manager::class, [ ':builder' => make( Builder::class ) ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\ST\MO\File;
|
||||
|
||||
trait makeDir {
|
||||
|
||||
/**
|
||||
* @var \WP_Filesystem_Direct
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/** @return bool */
|
||||
public function maybeCreateSubdir() {
|
||||
$subdir = $this->getSubdir();
|
||||
|
||||
if ( $this->filesystem->is_dir( $subdir ) && $this->filesystem->is_writable( $subdir ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->filesystem->mkdir( $subdir, 0755 & ~ umask() );
|
||||
}
|
||||
|
||||
/**
|
||||
* This declaration throws a "Strict standards" warning in PHP 5.6.
|
||||
* @todo: Remove the comment when we drop support for PHP 5.6.
|
||||
*/
|
||||
//abstract public static function getSubdir();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user