first commit

This commit is contained in:
User A0264400
2026-04-01 23:20:16 +03:00
commit a766acdc90
23071 changed files with 4933189 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
<?php
/**
* For buffering accidental output caused by themes and other plugins.
* Also used in template rendering.
*/
class Loco_output_Buffer {
/**
* The output buffering level opened by this instance
* @var int usually 1 unless another buffer was opened before this one.
*/
private $ob_level;
/**
* Content buffered while our buffer was buffering
* @var string
*/
private $output = '';
/**
* @return string
*/
public function __toString(){
return $this->output;
}
/**
* @return Loco_output_Buffer
*/
public static function start(){
$buffer = new Loco_output_Buffer;
return $buffer->open();
}
/**
* @internal
* Ensure buffers closed if something terminates before we close gracefully
*/
public function __destruct(){
$this->close();
}
/**
* @return Loco_output_Buffer
*/
public function open(){
self::check();
if( ! ob_start() ){
throw new Loco_error_Exception('Failed to start output buffering');
}
$this->ob_level = ob_get_level();
return $this;
}
/**
* @return Loco_output_Buffer
*/
public function close(){
if( is_int($this->ob_level) ){
// collect output from our nested buffers
$this->output = self::collect( $this->ob_level );
$this->ob_level = null;
}
return $this;
}
/**
* Trash all open buffers, logging any junk output collected
* @return void
*/
public function discard(){
$this->close();
if( '' !== $this->output ){
self::log_junk( $this->output );
$this->output = '';
}
}
/**
* Collect output buffered to a given level
* @param int $min highest buffer to flush, 0 being the root
* @return string
*/
public static function collect( $min ){
$last = 0;
$output = '';
while( $level = ob_get_level() ){
// @codeCoverageIgnoreStart
if( $level === $last ){
throw new Loco_error_Exception('Failed to close output buffer');
}
// @codeCoverageIgnoreEnd
if( $level < $min ){
break;
}
// output is appended inside out:
$output = ob_get_clean().$output;
$last = $level;
}
return $output;
}
/**
* Forcefully destroy all open buffers and log any bytes already buffered.
* @return void
*/
public static function clear(){
$junk = self::collect(0);
if( '' !== $junk ){
self::log_junk($junk);
}
}
/**
* Check output has not already been flushed.
* @throws Loco_error_Exception
*/
public static function check(){
if( headers_sent($file,$line) && 'cli' !== PHP_SAPI ){
$file = str_replace( trailingslashit( loco_constant('ABSPATH') ), '', $file );
// translators: (1) is the name of a PHP script, (2) is a line number in the file
throw new Loco_error_Exception( sprintf( __('Loco was interrupted by output from %1$s:%2$u','loco-translate'), $file?:'Unknown', $line ) );
}
}
/**
* Debug collection of junk output
* @param string $junk
* @return void
*/
private static function log_junk( $junk ){
$bytes = strlen($junk);
$message = sprintf("Cleared %s of buffered output", Loco_mvc_FileParams::renderBytes($bytes) );
Loco_error_AdminNotices::debug( $message );
do_action( 'loco_buffer_cleared', $junk );
}
}

View File

@@ -0,0 +1,90 @@
<?php
require_once ABSPATH . WPINC . '/Text/Diff.php';
require_once ABSPATH . WPINC . '/Text/Diff/Renderer.php';
require_once ABSPATH . WPINC . '/Text/Diff/Renderer/inline.php';
require_once ABSPATH . WPINC . '/wp-diff.php';
/**
* Diff renderer extending that which WordPress uses for post revisions.
*/
class Loco_output_DiffRenderer extends WP_Text_Diff_Renderer_Table {
/**
* {@inheritdoc}
*/
public function __construct( $params = [] ){
parent::__construct( $params + [
'show_split_view' => true,
'leading_context_lines' => 1,
'trailing_context_lines' => 1,
] );
}
/**
* Render diff of two files, presumed to be PO or POT
* @param Loco_fs_File Left hand file
* @param Loco_fs_File Right hand file
* @return string HTML table
*/
public function renderFiles( Loco_fs_File $lhs, Loco_fs_File $rhs ){
loco_require_lib('compiled/gettext.php');
// attempt to raise memory limit to WP_MAX_MEMORY_LIMIT
if( function_exists('wp_raise_memory_limit') ){
wp_raise_memory_limit('loco');
}
// like wp_text_diff but avoiding whitespace normalization
// uses deprecated signature for 'auto' in case of old WordPress
return $this->render( new Text_Diff( self::splitFile($lhs), self::splitFile($rhs) ) );
}
/**
* @param Loco_fs_File
* @return string[]
*/
private static function splitFile( Loco_fs_File $file ){
$src = $file->getContents();
$src = Loco_gettext_Data::ensureUtf8($src);
$arr = preg_split( '/\\r?\\n/', $src );
if( ! is_array($arr) ){
$f = new Loco_mvc_FileParams( [], $file );
throw new Loco_error_Exception('Failed to split '.$f->relpath.' ('.$f->size.')' );
}
return $arr;
}
/**
* {@inheritdoc}
*/
public function _startDiff() {
return "<table class=\"diff\">\n";
}
/**
* {@inheritdoc}
*/
public function _endDiff() {
return "</table>\n";
}
/**
* {@inheritdoc}
*/
public function _startBlock( $header ) {
return '<tbody data-diff="'.esc_attr($header)."\">\n";
}
/**
* {@inheritdoc}
*/
public function _endBlock() {
return "</tbody>\n";
}
}