generateMissingMoFile = $generateMissingMoFile; $this->optionManager = $optionManager; $this->moFilesDictionary = $moFilesDictionary; } public function add_hooks() { if ( $this->wasWpmlInstalledPriorToMoFlowChanges() ) { add_filter( 'load_textdomain_mofile', [ $this, 'recordMissing' ], 10, 2 ); add_action( 'shutdown', [ $this, 'generateMissing' ] ); } } /** * @param string $mofile * @param string $domain * * @return string */ public function recordMissing( $mofile, $domain ) { if ( strpos( $mofile, WP_LANG_DIR . '/themes/' ) === 0 ) { return $mofile; } if ( strpos( $mofile, WP_LANG_DIR . '/plugins/' ) === 0 ) { return $mofile; } $missing = $this->getMissing(); if ( self::isReadable( $mofile ) ) { if ( $missing->has( $domain ) ) { $this->saveMissing( $missing->forget( $domain ) ); } return $mofile; } if ( ! $this->moFilesDictionary->find( $mofile ) ) { return $mofile; } $generatedFile = $this->getGeneratedFileName( $mofile, $domain ); if ( self::isReadable( $generatedFile ) ) { return $generatedFile; } if ( $this->generateMissingMoFile->isNotProcessed( $generatedFile ) ) { $this->saveMissing( $missing->put( $domain, $mofile ) ); } return $mofile; } public function generateMissing() { $lock = make( 'WPML\Utilities\Lock', [ ':name' => self::class ] ); $missing = $this->getMissing(); if ( $missing->count() && $lock->create() ) { $generate = function ( $pair ) { list( $domain, $mofile ) = $pair; $generatedFile = $this->getGeneratedFileName( $mofile, $domain ); $this->generateMissingMoFile->run( $generatedFile, $domain ); }; $unProcessed = $missing->assocToPair() ->eachWithTimeout( $generate, self::getTimeout() ) ->pairToAssoc(); $this->saveMissing( $unProcessed ); $lock->release(); } } public static function isReadable( $mofile ) { return is_readable( $mofile ); } /** * @return \WPML\Collect\Support\Collection */ private function getMissing() { return wpml_collect( $this->optionManager->get( self::OPTION_GROUP, self::MISSING_MO_OPTION, [] ) ); } /** * @param \WPML\Collect\Support\Collection $missing */ private function saveMissing( \WPML\Collect\Support\Collection $missing ) { $this->optionManager->set( self::OPTION_GROUP, self::MISSING_MO_OPTION, $missing->toArray() ); } public static function getTimeout() { return self::TIMEOUT; } /** * @return bool */ private function wasWpmlInstalledPriorToMoFlowChanges() { $wpml_start_version = \get_option( \WPML_Installation::WPML_START_VERSION_KEY, '0.0.0' ); return version_compare( $wpml_start_version, self::WPML_VERSION_INTRODUCING_ST_MO_FLOW, '<' ); } /** * @param string $mofile * @param string $domain * * @return string */ private function getGeneratedFileName( $mofile, $domain ) { $fileName = basename( $mofile ); if ( $this->isNonDefaultWithMissingDomain( $fileName, $domain ) ) { $fileName = $domain . '-' . $fileName; } return WP_LANG_DIR . self::MISSING_MO_FILES_DIR . $fileName; } /** * There's a fallback for theme that is looking for * this kind of file `wp-content/themes/hybrid/ru_RU.mo`. * We need to add the domain otherwise it collides with * the MO file for the default domain. * * @param string $fileName * @param string $domain * * @return bool */ private function isNonDefaultWithMissingDomain( $fileName, $domain ) { return 'default' !== $domain && preg_match( '/^[a-z]+_?[A-Z]*\.mo$/', $fileName ); } }