first commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
class Entry {
|
||||
|
||||
/**
|
||||
* @var int $timestamp The log's creation timestamp.
|
||||
*/
|
||||
public $timestamp = 0;
|
||||
|
||||
/**
|
||||
* @see EventsTypes
|
||||
*
|
||||
* @var int $eventType The event code that triggered the log.
|
||||
*/
|
||||
public $eventType = 0;
|
||||
|
||||
/**
|
||||
* @var string $description The details of the log (e.g. exception message).
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
/**
|
||||
* @var int $wpmlJobId [Optional] The WPML Job ID (when applies).
|
||||
*/
|
||||
public $wpmlJobId = 0;
|
||||
|
||||
/**
|
||||
* @var int $ateJobId [Optional] The ATE Job ID (when applies).
|
||||
*/
|
||||
public $ateJobId = 0;
|
||||
|
||||
/**
|
||||
* @var array $extraData [Optional] Complementary serialized data (e.g. API request/response data).
|
||||
*/
|
||||
public $extraData = [];
|
||||
|
||||
/**
|
||||
* @param array $item
|
||||
*
|
||||
* @return Entry
|
||||
*/
|
||||
public function __construct( array $item = null ) {
|
||||
if ( $item ) {
|
||||
$this->timestamp = (int) $item['timestamp'];
|
||||
$this->eventType = (int) ( isset( $item['eventType'] ) ? $item['eventType'] : $item['event'] );
|
||||
$this->description = $item['description'];
|
||||
$this->wpmlJobId = (int) $item['wpmlJobId'];
|
||||
$this->ateJobId = (int) $item['ateJobId'];
|
||||
$this->extraData = (array) $item['extraData'];
|
||||
}
|
||||
}
|
||||
|
||||
public static function createForType($eventType, $extraData) {
|
||||
$entry = new self();
|
||||
$entry->eventType = $eventType;
|
||||
$entry->extraData = $extraData;
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
public static function retryJob( $wpmlJobId, $extraData ) {
|
||||
$entry = self::createForType(EventsTypes::JOB_RETRY, $extraData);
|
||||
$entry->wpmlJobId = $wpmlJobId;
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedDate() {
|
||||
return date_i18n( 'Y/m/d g:i:s A', $this->timestamp );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getExtraDataToString() {
|
||||
return json_encode( $this->extraData );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
class EventsTypes {
|
||||
|
||||
/** Communication errors */
|
||||
const SERVER_ATE = 1;
|
||||
const SERVER_AMS = 2;
|
||||
const SERVER_XLIFF = 3;
|
||||
|
||||
/** Internal errors */
|
||||
const JOB_DOWNLOAD = 10;
|
||||
|
||||
/** Retry */
|
||||
const JOB_RETRY = 20;
|
||||
const SITE_REGISTRATION_RETRY = 21;
|
||||
|
||||
/** Sync */
|
||||
const JOBS_SYNC = 30;
|
||||
|
||||
public static function getLabel( $eventType ) {
|
||||
return wpml_collect(
|
||||
[
|
||||
EventsTypes::SERVER_ATE => 'ATE Server Communication',
|
||||
EventsTypes::SERVER_AMS => 'AMS Server Communication',
|
||||
EventsTypes::SERVER_XLIFF => 'XLIFF Server Communication',
|
||||
EventsTypes::JOB_DOWNLOAD => 'Job Download',
|
||||
EventsTypes::JOB_RETRY => 'Job resent to ATE',
|
||||
EventsTypes::SITE_REGISTRATION_RETRY => 'Site registration request resent to ATE',
|
||||
EventsTypes::JOBS_SYNC => 'Jobs sync request sent to ATE failed',
|
||||
]
|
||||
)->get( $eventType, '' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
class Hooks implements \IWPML_Backend_Action, \IWPML_DIC_Action {
|
||||
|
||||
const SUBMENU_HANDLE = 'wpml-tm-ate-log';
|
||||
|
||||
/** @var ViewFactory $viewFactory */
|
||||
private $viewFactory;
|
||||
|
||||
public function __construct( ViewFactory $viewFactory ) {
|
||||
$this->viewFactory = $viewFactory;
|
||||
}
|
||||
|
||||
public function add_hooks() {
|
||||
add_action( 'wpml_support_page_after', [ $this, 'renderSupportSection' ] );
|
||||
add_action( 'admin_menu', [ $this, 'addLogSubmenuPage' ] );
|
||||
}
|
||||
|
||||
public function renderSupportSection() {
|
||||
$this->viewFactory->create()->renderSupportSection();
|
||||
}
|
||||
|
||||
public function addLogSubmenuPage() {
|
||||
add_submenu_page(
|
||||
WPML_PLUGIN_FOLDER . '/menu/support.php',
|
||||
__( 'Advanced Translation Editor Error Logs', 'wpml-translation-management' ),
|
||||
'ATE logs',
|
||||
'manage_options',
|
||||
self::SUBMENU_HANDLE,
|
||||
[ $this, 'renderPage' ]
|
||||
);
|
||||
}
|
||||
|
||||
public function renderPage() {
|
||||
$this->viewFactory->create()->renderPage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
use WPML\Collect\Support\Collection;
|
||||
use WPML\WP\OptionManager;
|
||||
|
||||
class Storage {
|
||||
|
||||
const OPTION_GROUP = 'TM\ATE\Log';
|
||||
const OPTION_NAME = 'logs';
|
||||
const MAX_ENTRIES = 50;
|
||||
|
||||
public static function add( Entry $entry, $avoidDuplication = false ) {
|
||||
$entry->timestamp = $entry->timestamp ?: time();
|
||||
|
||||
$entries = self::getAll();
|
||||
|
||||
if ( $avoidDuplication ) {
|
||||
$entries = $entries->reject(
|
||||
function( $iteratedEntry ) use ( $entry ) {
|
||||
return (
|
||||
$iteratedEntry->wpmlJobId === $entry->wpmlJobId
|
||||
&& $entry->ateJobId === $iteratedEntry->ateJobId
|
||||
&& $entry->description === $iteratedEntry->description
|
||||
&& $entry->eventType === $iteratedEntry->eventType
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$entries->prepend( $entry );
|
||||
|
||||
$newOptionValue = $entries->forPage( 1, self::MAX_ENTRIES )
|
||||
->map(
|
||||
function( Entry $entry ) {
|
||||
return (array) $entry; }
|
||||
)
|
||||
->toArray();
|
||||
OptionManager::updateWithoutAutoLoad( self::OPTION_NAME, self::OPTION_GROUP, $newOptionValue );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entry $entry
|
||||
*/
|
||||
public static function remove( Entry $entry ) {
|
||||
$entries = self::getAll();
|
||||
$entries = $entries->reject(
|
||||
function( $iteratedEntry ) use ( $entry ) {
|
||||
return $iteratedEntry->timestamp === $entry->timestamp && $entry->ateJobId === $iteratedEntry->ateJobId;
|
||||
}
|
||||
);
|
||||
$newOptionValue = $entries->forPage( 1, self::MAX_ENTRIES )
|
||||
->map(
|
||||
function( Entry $entry ) {
|
||||
return (array) $entry; }
|
||||
)
|
||||
->toArray();
|
||||
OptionManager::updateWithoutAutoLoad( self::OPTION_NAME, self::OPTION_GROUP, $newOptionValue );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection Collection of Entry objects.
|
||||
*/
|
||||
public static function getAll() {
|
||||
return wpml_collect( OptionManager::getOr( [], self::OPTION_NAME, self::OPTION_GROUP ) )
|
||||
->map(
|
||||
function( array $item ) {
|
||||
return new Entry( $item );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
use WPML\Collect\Support\Collection;
|
||||
|
||||
class View {
|
||||
|
||||
/** @var Collection $logs */
|
||||
private $logs;
|
||||
|
||||
public function __construct( Collection $logs ) {
|
||||
$this->logs = $logs;
|
||||
}
|
||||
|
||||
public function renderSupportSection() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2 id="ate-log">
|
||||
<?php esc_html_e( 'Advanced Translation Editor', 'wpml-translation-management' ); ?>
|
||||
</h2>
|
||||
<p>
|
||||
<a href="<?php echo admin_url( 'admin.php?page=' . Hooks::SUBMENU_HANDLE ); ?>">
|
||||
<?php echo sprintf( esc_html__( 'Error Logs (%d)', 'wpml-translation-management' ), $this->logs->count() ); ?>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function renderPage() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Advanced Translation Editor Error Logs', 'wpml-translation-management' ); ?></h1>
|
||||
<br>
|
||||
<table class="wp-list-table widefat fixed striped posts">
|
||||
<thead><?php $this->renderTableHeader(); ?></thead>
|
||||
|
||||
<tbody id="the-list">
|
||||
<?php
|
||||
if ( $this->logs->isEmpty() ) {
|
||||
$this->renderEmptyTable();
|
||||
} else {
|
||||
$this->logs->each( [ $this, 'renderTableRow' ] );
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot><?php $this->renderTableHeader(); ?></tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function renderTableHeader() {
|
||||
?>
|
||||
<tr>
|
||||
<th class="date">
|
||||
<span><?php esc_html_e( 'Date', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
<th class="event">
|
||||
<span><?php esc_html_e( 'Event', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
<th class="description">
|
||||
<span><?php esc_html_e( 'Description', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
<th class="wpml-job-id">
|
||||
<span><?php esc_html_e( 'WPML Job ID', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
<th class="ate-job-id">
|
||||
<span><?php esc_html_e( 'ATE Job ID', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
<th class="extra-data">
|
||||
<span><?php esc_html_e( 'Extra data', 'wpml-translation-management' ); ?></span>
|
||||
</th>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function renderTableRow( Entry $entry ) {
|
||||
?>
|
||||
<tr>
|
||||
<td class="date">
|
||||
<?php echo esc_html( $entry->getFormattedDate() ); ?>
|
||||
</td>
|
||||
<td class="event">
|
||||
<?php echo esc_html( EventsTypes::getLabel( $entry->eventType ) ); ?>
|
||||
</td>
|
||||
<td class="description">
|
||||
<?php echo esc_html( $entry->description ); ?>
|
||||
</td>
|
||||
<td class="wpml-job-id">
|
||||
<?php echo esc_html( $entry->wpmlJobId ); ?>
|
||||
</td>
|
||||
<td class="ate-job-id">
|
||||
<?php echo esc_html( $entry->ateJobId ); ?>
|
||||
</td>
|
||||
<td class="extra-data">
|
||||
<?php echo esc_html( $entry->getExtraDataToString() ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function renderEmptyTable() {
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="6" class="title column-title has-row-actions column-primary">
|
||||
<?php esc_html_e( 'No entries', 'wpml-translation-management' ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace WPML\TM\ATE\Log;
|
||||
|
||||
use function WPML\Container\make;
|
||||
|
||||
class ViewFactory {
|
||||
|
||||
public function create() {
|
||||
$logs = make( Storage::class )->getAll();
|
||||
|
||||
return new View( $logs );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user