| 1 |
<?php |
| 2 |
|
| 3 |
// Do performance / debug analysis |
| 4 |
|
| 5 |
namespace Microthemer\Content; |
| 6 |
|
| 7 |
use Microthemer\TimerTrait; |
| 8 |
|
| 9 |
class Debug { |
| 10 |
|
| 11 |
use TimerTrait; |
| 12 |
|
| 13 |
var $contentClass; |
| 14 |
var $m_queries = null; |
| 15 |
|
| 16 |
public function __construct(&$contentClass) { |
| 17 |
$this->contentClass = $contentClass; |
| 18 |
$this->m_queries = $this->getMQKeys(); |
| 19 |
} |
| 20 |
|
| 21 |
public function roundKB($size) { |
| 22 |
$kb = round($size, 2); |
| 23 |
return $kb . ' <span class="amender-unit">KB</span>'; |
| 24 |
} |
| 25 |
|
| 26 |
// We need m_queries, which is not available on the fronted preferences |
| 27 |
public function getMQKeys(){ |
| 28 |
$p = get_option('preferences_themer_loader'); |
| 29 |
if ($p){ |
| 30 |
return $p['m_queries']; |
| 31 |
} |
| 32 |
return null; |
| 33 |
} |
| 34 |
|
| 35 |
public function getKeyFromQuery($query){ |
| 36 |
|
| 37 |
$key = 'all-devices'; |
| 38 |
|
| 39 |
if ($this->m_queries && $query !== $key){ |
| 40 |
foreach ($this->m_queries as $mq_key => $array){ |
| 41 |
if (trim($query) === trim($array['query'])){ |
| 42 |
return $mq_key; |
| 43 |
} |
| 44 |
} |
| 45 |
} |
| 46 |
|
| 47 |
return $key; |
| 48 |
} |
| 49 |
|
| 50 |
public function generateHTML($debugAmends, &$modList, &$profiler, &$memoryProfiler, &$clientSide, &$logsArray, &$lazy) { |
| 51 |
|
| 52 |
$display = ''; |
| 53 |
$devData = ''; |
| 54 |
|
| 55 |
// show debug data |
| 56 |
if ($debugAmends){ |
| 57 |
|
| 58 |
// Performance table (time + memory) |
| 59 |
$zeroClientMods = empty($clientSide['clientModsCount']) ? 1 : 0; |
| 60 |
$zeroServerMods = empty($clientSide['serverModsCount']) ? 1 : 0; |
| 61 |
$zeroMods = $zeroClientMods && $zeroServerMods; |
| 62 |
|
| 63 |
// --- Time --- |
| 64 |
$assetPrepTime = !$zeroMods && isset($profiler['preparing_client_side_assets']['total_time']) |
| 65 |
? $profiler['preparing_client_side_assets']['total_time'] * 1000 // to ms |
| 66 |
: 0; |
| 67 |
|
| 68 |
$assetPrepLabel = round($assetPrepTime, 2).' <span class="amender-unit">ms</span>'; |
| 69 |
$htmlModsLabel = $zeroServerMods ? '0 <span class="amender-unit">ms</span>' : 'checking...'; |
| 70 |
$totalModsLabel = $zeroServerMods ? $assetPrepLabel : 'checking...'; |
| 71 |
|
| 72 |
// --- Memory (avg net retained + max peak overhead) --- |
| 73 |
$assetPrepMemDelta = !$zeroMods && isset($memoryProfiler['preparing_client_side_assets']['avg_delta']) |
| 74 |
? $memoryProfiler['preparing_client_side_assets']['avg_delta'] |
| 75 |
: 0; |
| 76 |
$assetPrepMemDeltaLabel = $this->formatBytes($assetPrepMemDelta); |
| 77 |
|
| 78 |
$htmlAdjustMemDeltaLabel = $zeroServerMods |
| 79 |
? $this->formatBytes(0) |
| 80 |
: 'checking...'; |
| 81 |
|
| 82 |
$totalMemDeltaLabel = $zeroServerMods |
| 83 |
? $assetPrepMemDeltaLabel |
| 84 |
: 'checking...'; |
| 85 |
|
| 86 |
$assetPrepPeak = isset($memoryProfiler['preparing_client_side_assets']['max_peak_window']) |
| 87 |
? $memoryProfiler['preparing_client_side_assets']['max_peak_window'] |
| 88 |
: 0; |
| 89 |
$assetPrepPeakLabel = $this->formatBytes($assetPrepPeak); |
| 90 |
|
| 91 |
|
| 92 |
$htmlAdjustPeakLabel = $zeroServerMods |
| 93 |
? $this->formatBytes(0) |
| 94 |
: 'checking...'; |
| 95 |
|
| 96 |
$totalPeak = $zeroServerMods |
| 97 |
? $assetPrepPeakLabel |
| 98 |
: 'checking...'; |
| 99 |
|
| 100 |
// --- Table HTML --- |
| 101 |
$performance = ' |
| 102 |
<div class="amender-data-table amender-performance-table"> |
| 103 |
<div class="amender-column-heading"></div> |
| 104 |
<div class="amender-column-heading">Asset Preparation</div> |
| 105 |
<div class="amender-column-heading">HTML Adjustments</div> |
| 106 |
<div class="amender-column-heading"><strong>Total</strong></div> |
| 107 |
|
| 108 |
<div class="amender-column-heading">Time (milliseconds):</div> |
| 109 |
<div id="server-asset-timing" data-time="'.round($assetPrepTime, 2).'">'.$assetPrepLabel.'</div> |
| 110 |
<div id="server-html-timing" data-zero-mods="'.$zeroServerMods.'">'.$htmlModsLabel.'</div> |
| 111 |
<div id="server-total-timing"><strong>'.$totalModsLabel.'</strong></div> |
| 112 |
|
| 113 |
</div>'; |
| 114 |
|
| 115 |
/* |
| 116 |
* <div class="amender-column-heading">Net Memory Retained:</div> |
| 117 |
<div id="server-asset-mem" data-bytes="'.$assetPrepMemDelta.'">'.$assetPrepMemDeltaLabel.'</div> |
| 118 |
<div id="server-html-mem" data-zero-mods="'.$zeroServerMods.'">'.$htmlAdjustMemDeltaLabel.'</div> |
| 119 |
<div id="server-total-mem"><strong>'.$totalMemDeltaLabel.'</strong></div> |
| 120 |
|
| 121 |
<div class="amender-column-heading">Peak Extra Allocation:</div> |
| 122 |
<div id="server-asset-peak" data-bytes="'.$assetPrepPeak.'">'.$assetPrepPeakLabel.'</div> |
| 123 |
<div id="server-html-peak" data-zero-mods="'.$zeroServerMods.'">'.$htmlAdjustPeakLabel.'</div> |
| 124 |
<div id="server-total-peak"><strong>'.$totalPeak.'</strong></div> |
| 125 |
*/ |
| 126 |
|
| 127 |
// User CSS (todo need to include MT CSS) |
| 128 |
$css = implode("\n", $clientSide['css']); |
| 129 |
|
| 130 |
// JS functions and file contents |
| 131 |
$js = !$zeroClientMods && $clientSide['inline_functions'] |
| 132 |
? "// Inline JS Functions \n" . $clientSide['inline_functions'] |
| 133 |
: ''; |
| 134 |
|
| 135 |
foreach ($clientSide['js'] as $slug){ |
| 136 |
$js.= "// ".$slug.".js\n" . |
| 137 |
file_get_contents($this->contentClass->getLocalJsFile($slug, 0, 0, 1)) . "\n\n"; |
| 138 |
} |
| 139 |
|
| 140 |
$this->contentClass->accumulateSizeKB( |
| 141 |
'user_css', |
| 142 |
$clientSide, |
| 143 |
$css |
| 144 |
); |
| 145 |
|
| 146 |
$this->contentClass->accumulateSizeKB( |
| 147 |
'user_js', |
| 148 |
$clientSide, |
| 149 |
$js |
| 150 |
); |
| 151 |
|
| 152 |
$asset_size = $clientSide['asset_size']; |
| 153 |
$totalSize = 0; |
| 154 |
if (!$zeroClientMods){ |
| 155 |
foreach ($asset_size as $key => $value){ |
| 156 |
if ($key === 'debug_only_data'){ |
| 157 |
$totalSize -= $value; |
| 158 |
} else { |
| 159 |
$totalSize += $value; |
| 160 |
} |
| 161 |
} |
| 162 |
} |
| 163 |
|
| 164 |
$size = ' |
| 165 |
<div class="amender-data-table amender-size-table"> |
| 166 |
<div class="amender-column-heading">CSS</div> |
| 167 |
<div class="amender-column-heading">JS</div> |
| 168 |
<div class="amender-column-heading">JS Packages</div> |
| 169 |
<div class="amender-column-heading">Modifications JSON</div> |
| 170 |
<div class="amender-column-heading">Amender Scripts</div> |
| 171 |
|
| 172 |
<div class="amender-column-heading"><strong>Total Size</strong></div> |
| 173 |
<div>'.$this->roundKB($asset_size['user_css']).'</div> |
| 174 |
<div>'.$this->roundKB($asset_size['user_js']).'</div> |
| 175 |
<div>'.$this->roundKB($asset_size['user_packages']).'</div> |
| 176 |
<div>'. |
| 177 |
($zeroClientMods |
| 178 |
? '0 <span class="amender-unit">KB</span>' |
| 179 |
: $this->roundKB($asset_size['amender_inline'] - $asset_size['debug_only_data']) |
| 180 |
) |
| 181 |
.'</div> |
| 182 |
<div>'. |
| 183 |
($zeroClientMods |
| 184 |
? '0 <span class="amender-unit">KB</span>' |
| 185 |
: $this->roundKB($asset_size['amender_packages']) |
| 186 |
) |
| 187 |
.'</div> |
| 188 |
<div><strong>'.$this->roundKB($totalSize).'</strong></div> |
| 189 |
</div>'; |
| 190 |
$user_packages = ' |
| 191 |
<div class="amender-data-table amender-packages-table"> |
| 192 |
<div class="amender-column-heading">Package</div> |
| 193 |
<div class="amender-column-heading">Size</div> |
| 194 |
<div class="amender-column-heading">Version</div> |
| 195 |
<div class="amender-column-heading">URL</div> |
| 196 |
|
| 197 |
'; |
| 198 |
|
| 199 |
$hasPackages = false; |
| 200 |
|
| 201 |
// Show message about no modifications if relevant |
| 202 |
if ($zeroMods){ |
| 203 |
$table = 'No modifications have been made.'; |
| 204 |
} |
| 205 |
|
| 206 |
else { |
| 207 |
$table = ' |
| 208 |
<div class="amender-data-table amender-modification-table"> |
| 209 |
<div class="amender-column-heading">Edit</div> |
| 210 |
<div class="amender-column-heading">Event</div> |
| 211 |
<div class="amender-column-heading">Devices</div> |
| 212 |
<div class="amender-column-heading">Selector</div> |
| 213 |
<div class="amender-column-heading">Action</div> |
| 214 |
<div class="amender-column-heading">Aspect</div> |
| 215 |
<div class="amender-column-heading">Content</div> |
| 216 |
'; |
| 217 |
|
| 218 |
//$debugRows = array(); |
| 219 |
/*foreach ($modList as $item){ |
| 220 |
$item[3] = esc_html($item[3]); |
| 221 |
//$debugRows[] = $item; |
| 222 |
$table.= |
| 223 |
' |
| 224 |
<div>serverHTMLReady</div> |
| 225 |
<div>'.esc_html($item[6]).'</div> |
| 226 |
<div>'.esc_html($item[5]).'</div> |
| 227 |
<div>'.esc_html($item[1]['action']).'</div> |
| 228 |
<div>'.esc_html($item[1]['aspect']).'</div> |
| 229 |
<div>'.esc_html($item[3]).'</div> |
| 230 |
'; |
| 231 |
}*/ |
| 232 |
|
| 233 |
// Server and client side amendments (always dyn when reviewing) |
| 234 |
foreach ($clientSide['mods'] as $event => $devices){ |
| 235 |
foreach ($devices as $query => $selectors){ |
| 236 |
foreach ($selectors as $selectorId => $data){ |
| 237 |
foreach ($data['mods'] as $index => $modData){ |
| 238 |
$mod = $modData['mod']; |
| 239 |
$table.= |
| 240 |
' |
| 241 |
<div class="edit-modification mt-ui-element" data-id="'.$selectorId.'" data-index="'.$index.'" |
| 242 |
data-mq_key="'.$this->getKeyFromQuery($query).'" data-pg="html" data-property="action">Edit</div> |
| 243 |
<div>'.esc_html($event).'</div> |
| 244 |
<div>'.esc_html($query).'</div> |
| 245 |
<div>'.esc_html($data['selectorCode']).'</div> |
| 246 |
<div>'.esc_html($mod['action']).'</div> |
| 247 |
<div>'.esc_html($mod['aspect']).'</div> |
| 248 |
<div>'.esc_html($modData['debugValue']).'</div> |
| 249 |
|
| 250 |
'; |
| 251 |
} |
| 252 |
} |
| 253 |
} |
| 254 |
} |
| 255 |
|
| 256 |
|
| 257 |
$table.= '</div>'; |
| 258 |
} |
| 259 |
|
| 260 |
// List packages, including size breakdown |
| 261 |
|
| 262 |
foreach ($clientSide['import_map'] as $packageName => $one){ |
| 263 |
$dep = $this->contentClass->getDependencyInfo($packageName); |
| 264 |
$dep['deliveryUrl'] = $this->contentClass->deliveryUrl( |
| 265 |
$dep, |
| 266 |
$dep['value'], |
| 267 |
$this->contentClass->assetClass->micro_root_dir . 'mt/js/'.$this->contentClass->assetClass->fileStub.'/npm/' |
| 268 |
); |
| 269 |
$url = $dep['deliveryUrl']; |
| 270 |
|
| 271 |
$user_packages.= ' |
| 272 |
<div>'.$dep['value'].'</div> |
| 273 |
<div>'.$dep['size'].' <span class="amender-unit">KB</span></div> |
| 274 |
<div>'.$dep['version'].'</div> |
| 275 |
|
| 276 |
<div><a target="_blank" href="'.$url.'">'.$url.'</a></div> |
| 277 |
'; |
| 278 |
|
| 279 |
$hasPackages = true; |
| 280 |
|
| 281 |
/*$devData.= '<div class="amender-data-title">Package: '.esc_html($packageName).'</div> |
| 282 |
<div class="amender-data-content"><pre>'.esc_html(print_r($dep, 1)).'</pre></div>';*/ |
| 283 |
|
| 284 |
} |
| 285 |
$user_packages.= ' |
| 286 |
<div class="amender-column-heading">Total</div> |
| 287 |
<div><strong>'.$this->roundKB($asset_size['user_packages']).'</strong></div> |
| 288 |
</div>'; |
| 289 |
|
| 290 |
|
| 291 |
|
| 292 |
|
| 293 |
// Dev only |
| 294 |
|
| 295 |
if ($this->contentClass->devMode){ |
| 296 |
|
| 297 |
$devData.= '<div class="amender-data-title">Dev clientSide</div> |
| 298 |
<div class="amender-data-content"><pre>'.esc_html(print_r($clientSide, 1)).'</pre></div>'; |
| 299 |
|
| 300 |
// Lazyloaded content |
| 301 |
$devData.= '<div class="amender-data-title">Lazy content</div> |
| 302 |
<div class="amender-data-content"><pre>'.esc_html(print_r($lazy, 1)).'</pre></div>'; |
| 303 |
|
| 304 |
} |
| 305 |
|
| 306 |
$packagesList = $hasPackages |
| 307 |
? ' |
| 308 |
<div class="amender-data-title">JS Packages</div> |
| 309 |
<div class="amender-data-content">'.$user_packages.'</div>' |
| 310 |
: ''; |
| 311 |
|
| 312 |
// <div class="amender-data-content"><pre>'.print_r($debugRows, 1).'</pre></div> |
| 313 |
$display.= ' |
| 314 |
<div id="amender-data"> |
| 315 |
<div class="amender-data-title">Server-side Performance</div> |
| 316 |
<div class="amender-data-content">'.$performance.'</div> |
| 317 |
|
| 318 |
<div class="amender-data-title">Asset Size</div> |
| 319 |
<div class="amender-data-content">'.$size.'</div> |
| 320 |
<div class="amender-data-title">Modifications</div> |
| 321 |
<div class="amender-data-content">'.$table.'</div> |
| 322 |
'.($css |
| 323 |
? '<div class="amender-data-title">CSS</div> |
| 324 |
<div class="amender-data-content"><pre>'.esc_html($css).'</pre></div>' |
| 325 |
: ''). |
| 326 |
($js |
| 327 |
? '<div class="amender-data-title">JS</div> |
| 328 |
<div class="amender-data-content"><pre>'.esc_html($js).'</pre></div>' |
| 329 |
: '').' |
| 330 |
' . $packagesList . $devData.' |
| 331 |
</div>'; |
| 332 |
|
| 333 |
} |
| 334 |
|
| 335 |
// Show errors |
| 336 |
if (count($logsArray)){ |
| 337 |
|
| 338 |
$heading = '<div class="error-heading">Amender errors ('.count($logsArray).')</div>'; |
| 339 |
$logs = ''; |
| 340 |
|
| 341 |
foreach ($logsArray as $item){ |
| 342 |
$data = $item['data'] |
| 343 |
? '<pre class="error-data">'.esc_html(print_r($item['data'], 1)).'</pre>' |
| 344 |
: ''; |
| 345 |
|
| 346 |
$logs.= ' |
| 347 |
<li class="error-item error-type-'.$item['type'].'"> |
| 348 |
<span>'.$item['message'].'</span> |
| 349 |
'.$data.' |
| 350 |
</li>'; |
| 351 |
} |
| 352 |
|
| 353 |
$display.= ' |
| 354 |
<div id="amender-errors"> |
| 355 |
'.$heading.' |
| 356 |
<ul>'.$logs.'</ul> |
| 357 |
</div>'; |
| 358 |
|
| 359 |
} |
| 360 |
|
| 361 |
return $display; |
| 362 |
|
| 363 |
} |
| 364 |
} |