44 Commits
Author SHA1 Message Date
Andrey Savchenko 357753f84b Updated changelog and version for 1.3.2 2015-08-27 14:06:08 +03:00
Andrey Savchenko 9d1dddb462 Normalized slashing on adding files to release zip file. 2015-08-27 14:05:48 +03:00
Andrey Savchenko d88a566aee Fixed dynamic method call to prevent crash on PHP 7. 2015-08-27 14:05:19 +03:00
Andrey Savchenko b976b26454 Updated version in header 2015-08-15 21:06:35 +03:00
Andrey Savchenko a00b11f78a Updated changelog for 1.3.1 2015-08-12 00:15:24 +03:00
Andrey Savchenko 32f300af7f Added check to catch event stops without matching starts
Fixes #7
2015-08-12 00:14:33 +03:00
Andrey Savchenko a3572063d2 Updated changelog and version 2015-06-12 22:06:33 +03:00
Andrey Savchenko e8f8e9a4b6 Implemented release command in robo 2015-06-12 21:06:07 +03:00
Andrey Savchenko cf44efbe64 Added version getter to robo file 2015-06-12 21:05:50 +03:00
Andrey Savchenko 2289923666 Updated main file for code style 2015-06-12 21:05:24 +03:00
Andrey Savchenko b82cd35cf8 Updated gitignore 2015-06-12 20:58:52 +03:00
Andrey Savchenko 8e441c935f Added task to set plugin version 2015-06-11 17:23:31 +03:00
Andrey Savchenko 7dfea751f5 Made method calls more compact 2015-06-11 12:40:19 +03:00
Andrey Savchenko a3cc36b661 Removed commented out debug code 2015-06-11 12:40:07 +03:00
Andrey Savchenko 47caf94cfe Another end of file new line 2015-06-11 12:33:45 +03:00
Andrey Savchenko d8298b1700 Made comparisons strict 2015-06-11 12:27:28 +03:00
Andrey Savchenko 5072bbbaad Added new lines to end of files for code style 2015-06-11 12:26:27 +03:00
Andrey Savchenko b32d60dfce Updated Stopwatch dependency 2015-06-11 12:26:00 +03:00
Andrey Savchenko c593e1e925 Tightened condition on Hybrid events to prevent breakage with v3
Fixes #4
2015-06-11 11:56:02 +03:00
Andrey Savchenko 112c14fde3 Added events class for Yoast plugins 2015-04-06 10:19:57 +03:00
Andrey Savchenko df40e389ad Precompiled Mustache template 2015-04-06 09:46:09 +03:00
Andrey Savchenko fb7b2f025a Added Robo task for precompiling Mustache cache 2015-04-06 09:45:44 +03:00
Andrey Savchenko b87ce58f4a Implemented class for loading precompiled Mustache cache 2015-04-06 09:45:12 +03:00
Andrey Savchenko 424fb74b29 Updated dependencies 2015-04-06 09:44:18 +03:00
Andrey Savchenko 5ed687499f Recompiled assets after dependencies update 2015-03-28 23:36:08 +02:00
Andrey Savchenko 1db8318edb Updated dependencies 2015-03-28 23:35:05 +02:00
Andrey Savchenko edb804d35f Update README.md
Added link to releases section for archive download.
2015-02-06 23:20:32 +01:00
Andrey Savchenko ce265e6dd2 Updated array keys for coding style. 2015-01-03 21:24:58 +02:00
Andrey Savchenko f3438de84b Implemented minified assets in queue. 2015-01-03 21:06:32 +02:00
Andrey Savchenko d0d70fddaf Recompiled assets. 2015-01-03 21:06:11 +02:00
Andrey Savchenko 48424c2b4c Updated RoboFile for less sourcemap and minified assets. 2015-01-03 21:05:40 +02:00
Andrey Savchenko b3be169798 Updated dependencies. 2015-01-03 20:49:14 +02:00
Andrey Savchenko 5a33c9329b Split plugins load into file load and following hook. 2014-11-07 20:55:37 +02:00
Andrey Savchenko 6fda82d443 Recompiled assets after Bootstrap update. 2014-10-30 17:34:15 +02:00
Andrey Savchenko c912f263a2 Updated Bootstrap dependency to 3.3.0 2014-10-30 17:32:56 +02:00
Andrey Savchenko 6c75879465 Adjusted command name in RoboFile to make what, not what from. 2014-10-24 15:42:22 +03:00
Andrey Savchenko db87114e3f Elaborated on Composer code use in license section. 2014-10-24 15:10:12 +03:00
Andrey Savchenko 6c7b6d6195 Added links to themes and docs. 2014-10-24 15:09:47 +03:00
Andrey Savchenko 40fd25490b Moved screenshot up for eye candy. 2014-10-24 15:09:22 +03:00
Andrey Savchenko f2f3c4f474 Updated dependencies. 2014-10-23 22:38:26 +03:00
Andrey Savchenko 59bc49bd56 Updated readme and moved changelog to separate file. 2014-10-23 22:15:24 +03:00
Andrey Savchenko 234ed808aa Recompiled JS and updated for new script name. 2014-10-23 22:11:53 +03:00
Andrey Savchenko b5161c2955 Updated compilation and watch commands in RoboFile. 2014-10-23 22:11:06 +03:00
Andrey Savchenko 4cdf206de9 Moved JS from inline PHP to own source file. 2014-10-23 22:09:48 +03:00
18 changed files with 676 additions and 199 deletions

No files matched your search

+2 -1
View File
@@ -1 +1,2 @@
vendor
/vendor
/release
+39
View File
@@ -0,0 +1,39 @@
# Changelog
## 1.3.2
- fixed dynamic method call crash on PHP 7
- fixed issue with slashes in generated release archives
## 1.3.1
- fixed crash on event stop without matching start
## 1.3
- implemented minified assets
- implemented pre-cached template
- fixed crash with upcoming Hybrid Core v3
- implemented release build command
- split plugins_loaded hook into separate event
- added WP SEO event
## 1.2.1
- disabled tooltip animation to fix JS errors and UI disappearing from under cursor
## 1.2
- merged RP with additional core events in admin
- implemented (ballpark) toolbar event
- fixed issue with event offsets in timelines
## 1.1
- added SQL timeline
- added HTTP timeline
- switched tooltips implementation to Bootstrap script
## 1.0
- Initial public release
+13 -35
View File
@@ -1,4 +1,6 @@
# Laps — light WP profiler
# Laps — light WordPress profiler
![Laps screenshot](http://i.imgur.com/zFokmkU.png)
Laps is light WordPress profiler (in a plugin), which aims to be:
@@ -16,53 +18,29 @@ Out of the box Laps supports common stage of WordPress page life cycle:
And some of third party hooks conventions for themes using:
- Theme Hook Alliance
- Hybrid
- Genesis
- Thematic
- [Theme Hook Alliance](http://zamoose.github.io/themehookalliance/)
- [Hybrid](http://themehybrid.com/)
- [Genesis](http://my.studiopress.com/themes/genesis/)
- [Thematic](http://thematictheme.com/)
There are also additional optional timelines, displaying:
- SQL queries (with `SAVEQUERIES` constant enabled)
- SQL queries (with [`SAVEQUERIES` constant](http://codex.wordpress.org/Editing_wp-config.php#Save_queries_for_analysis) enabled)
- HTTP requests performed
# Screenshot
## Installation
![Laps screenshot](http://i.imgur.com/zFokmkU.png)
Download plugin archive from [releases section](https://github.com/Rarst/laps/releases).
# Installation
Laps is a Composer package and can be installed in plugin directory via:
Or install in plugin directory via [Composer](https://getcomposer.org/):
composer create-project rarst/laps --no-dev
# Changelog
## 1.2.1
- disabled tooltip animation to fix JS errors and UI disappearing from under cursor
## 1.2
- merged RP with additional core events in admin
- implemented (ballpark) toolbar event
- fixed issue with event offsets in timelines
## 1.1
- added SQL timeline
- added HTTP timeline
- switched tooltips implementation to Bootstrap script
## 1.0
- Initial public release
# License Info
## License Info
Laps own code is licensed under MIT and it makes use of code from:
- Composer (MIT)
- Composer Installers (MIT)
- Symfony Stopwatch (MIT)
- Mustache.php (MIT)
- Twitter Bootstrap (MIT)
+127 -19
View File
@@ -1,5 +1,7 @@
<?php
require __DIR__ . '/vendor/autoload.php';
/**
* This is project's console commands configuration for Robo task runner.
*
@@ -12,40 +14,146 @@ class RoboFile extends \Robo\Tasks {
*/
public function watch() {
$less_callback = function () {
$this->less();
};
$this->taskWatch()
->monitor( 'css/variables.less', $less_callback )
->monitor( 'css/laps.less', $less_callback )
->monitor( [ 'css/variables.less', 'css/laps.less' ], function () {
$this->makeCss();
} )
->monitor( 'js/source.js', function () {
$this->makeJs();
} )
->run();
}
/**
* Compiles stylesheet from less into css.
* Compiles all assets.
*/
public function less() {
public function makeAll() {
$this->taskExec( 'lessc css/laps.less css/laps.css' )->run();
$this->makeCss();
$this->makeJs();
$this->makeMustache();
}
/**
* Copies tooltip.js from Bootstrap sources and edits plugin name.
* Compiles plugin's css file from less.
*/
public function tooltip() {
public function makeCss() {
$replacements = array(
'+function ($) {' => '// modified to use lapstooltip as plugin name' . "\n\n" . '+function ($) {',
'this.init(\'tooltip\'' => 'this.init(\'lapstooltip\'',
'bs.tooltip' => 'bs.lapstooltip',
'$.fn.tooltip' => '$.fn.lapstooltip',
$this->taskExec( 'lessc css/laps.less css/laps.css --source-map=css/laps.css.map' )->run();
$this->taskMinify( 'css/laps.css' )
->run();
}
/**
* Creates plugin's script file.
*/
public function makeJs() {
$this->taskConcat( [
'vendor/twbs/bootstrap/js/tooltip.js',
'js/source.js',
] )
->to( 'js/laps.js' )
->run();
$this->taskMinify( 'js/laps.js' )
->run();
}
/**
* Compiles plugin's mustache template
*/
public function makeMustache() {
$dir = __DIR__ . '/views/cache';
$this->_cleanDir( $dir );
$mustache = new \Mustache_Engine(
array(
'loader' => new \Mustache_Loader_FilesystemLoader( __DIR__ . '/views' ),
'cache' => $dir,
)
);
$mustache->loadTemplate( 'laps' );
}
$source = strtr( file_get_contents( 'vendor/twbs/bootstrap/js/tooltip.js' ), $replacements );
/**
* @return string
*/
private function versionGet() {
$this->taskWriteToFile( 'js/tooltip.js' )
->text( $source )
$content = file_get_contents( __DIR__ . '/laps.php' );
if ( false !== preg_match( '|^Version: (?P<version>.+)$|m', $content, $matches ) ) {
return trim( $matches['version'] );
}
return '';
}
/**
* Sets the plugin version in header.
*
* @param string $version Version string.
*/
public function versionSet( $version ) {
$this->taskReplaceInFile( 'laps.php' )
->regex( '|^Version:.*$|m' )
->to( 'Version: ' . $version )
->run();
}
/**
* Creates release zip
*
* @param string $version
*/
public function makeRelease( $version = '' ) {
if ( empty( $version ) ) {
$version = $this->versionGet();
}
$this->taskFileSystemStack()
->mkdir( 'release' )
->run();
$this->taskCleanDir( 'release' )->run();
$this->taskExec( 'composer' )
->dir( __DIR__ . '/release' )
->arg( 'create-project rarst/laps laps ' . $version )
->arg( '--prefer-dist --no-dev' )
->run();
$this->taskExec( 'composer' )
->dir( __DIR__ . '/release/laps' )
->arg( 'dump-autoload --optimize' )
->run();
$zipFile = "release/laps-{$version}.zip";
$zipArchive = new ZipArchive();
if ( ! $zipArchive->open( $zipFile, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ) ) {
die( "Failed to create archive\n" );
}
$finder = new Symfony\Component\Finder\Finder();
$finder->files()->in( 'release/laps' )->ignoreDotFiles( false );
/** @var \Symfony\Component\Finder\SplFileInfo $file */
foreach ( $finder as $file ) {
$relativePathname = str_replace( '\\', '/', $file->getRelativePathname() );
$zipArchive->addFile( $file->getRealPath(), 'laps/' . $relativePathname );
}
if ( ! $zipArchive->status === ZIPARCHIVE::ER_OK ) {
echo "Failed to write files to zip\n";
}
$zipArchive->close();
$this->taskDeleteDir( 'release/laps' )->run();
}
}
Generated
+43 -34
View File
@@ -1,23 +1,23 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "7495421e8df337988c9906e05aab637b",
"packages": [
{
"name": "composer/installers",
"version": "v1.0.15",
"version": "v1.0.21",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
"reference": "8e6a72a78f6cfd537fde3350720dfdc9ae3c5621"
"reference": "d64e23fce42a4063d63262b19b8e7c0f3b5e4c45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/installers/zipball/8e6a72a78f6cfd537fde3350720dfdc9ae3c5621",
"reference": "8e6a72a78f6cfd537fde3350720dfdc9ae3c5621",
"url": "https://api.github.com/repos/composer/installers/zipball/d64e23fce42a4063d63262b19b8e7c0f3b5e4c45",
"reference": "d64e23fce42a4063d63262b19b8e7c0f3b5e4c45",
"shasum": ""
},
"replace": {
@@ -48,8 +48,7 @@
{
"name": "Kyle Robinson Young",
"email": "kyle@dontkry.com",
"homepage": "https://github.com/shama",
"role": "Developer"
"homepage": "https://github.com/shama"
}
],
"description": "A multi-framework Composer library installer",
@@ -60,17 +59,23 @@
"Hurad",
"MODX Evo",
"OXID",
"SMF",
"Thelia",
"WolfCMS",
"agl",
"aimeos",
"annotatecms",
"bitrix",
"cakephp",
"chef",
"codeigniter",
"concrete5",
"croogo",
"dokuwiki",
"drupal",
"elgg",
"fuelphp",
"grav",
"installer",
"joomla",
"kohana",
@@ -84,6 +89,7 @@
"phpbb",
"piwik",
"ppi",
"puppet",
"roundcube",
"shopware",
"silverstripe",
@@ -93,27 +99,28 @@
"zend",
"zikula"
],
"time": "2014-06-23 16:25:28"
"time": "2015-02-18 17:17:01"
},
{
"name": "mustache/mustache",
"version": "v2.6.1",
"version": "v2.8.0",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/mustache.php.git",
"reference": "1430ca884912eaba2b3830856b45685733b16789"
"reference": "64c28cc73e01d5edcef7de8cb2b16782615f648a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/1430ca884912eaba2b3830856b45685733b16789",
"reference": "1430ca884912eaba2b3830856b45685733b16789",
"url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/64c28cc73e01d5edcef7de8cb2b16782615f648a",
"reference": "64c28cc73e01d5edcef7de8cb2b16782615f648a",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"require-dev": {
"phpunit/phpunit": "*"
"fabpot/php-cs-fixer": "~1.6",
"phpunit/phpunit": "~3.7|~4.0"
},
"type": "library",
"autoload": {
@@ -138,34 +145,36 @@
"mustache",
"templating"
],
"time": "2014-06-20 19:34:49"
"time": "2015-04-01 06:37:33"
},
{
"name": "symfony/stopwatch",
"version": "v2.5.0",
"target-dir": "Symfony/Component/Stopwatch",
"version": "v2.7.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/Stopwatch.git",
"reference": "724d73604ebe6c1c9bdf36533b556123bd9075a1"
"reference": "7702945bceddc0e1f744519abb8a2baeb94bd5ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/724d73604ebe6c1c9bdf36533b556123bd9075a1",
"reference": "724d73604ebe6c1c9bdf36533b556123bd9075a1",
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/7702945bceddc0e1f744519abb8a2baeb94bd5ce",
"reference": "7702945bceddc0e1f744519abb8a2baeb94bd5ce",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=5.3.9"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
"dev-master": "2.7-dev"
}
},
"autoload": {
"psr-0": {
"psr-4": {
"Symfony\\Component\\Stopwatch\\": ""
}
},
@@ -176,33 +185,31 @@
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "http://symfony.com/contributors"
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Stopwatch Component",
"homepage": "http://symfony.com",
"time": "2014-04-18 20:40:13"
"homepage": "https://symfony.com",
"time": "2015-05-02 15:21:08"
}
],
"packages-dev": [
{
"name": "twbs/bootstrap",
"version": "v3.2.0",
"version": "v3.3.4",
"source": {
"type": "git",
"url": "https://github.com/twbs/bootstrap.git",
"reference": "c068162161154a4b85110ea1e7dd3d7897ce2b72"
"reference": "a10eb60bc0b07b747fa0c4ebd8821eb7307bd07f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/c068162161154a4b85110ea1e7dd3d7897ce2b72",
"reference": "c068162161154a4b85110ea1e7dd3d7897ce2b72",
"url": "https://api.github.com/repos/twbs/bootstrap/zipball/a10eb60bc0b07b747fa0c4ebd8821eb7307bd07f",
"reference": "a10eb60bc0b07b747fa0c4ebd8821eb7307bd07f",
"shasum": ""
},
"replace": {
@@ -211,7 +218,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev"
"dev-master": "3.3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -240,12 +247,14 @@
"responsive",
"web"
],
"time": "2014-06-26 16:36:48"
"time": "2015-03-16 15:44:41"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
+11 -16
View File
@@ -45,17 +45,6 @@
border-left: 1px solid #f5f5f5;
min-width: 2px;
}
#wpadminbar .laps-timeline .event[aria-valuenow="1"],
#wpadminbar .laps-timeline .event[aria-valuenow="2"] {
min-width: 30px;
}
#wpadminbar .laps-timeline .event[aria-valuenow="0"] {
color: #777777;
min-width: 30px;
background-color: transparent;
background-image: none;
box-shadow: none;
}
#wpadminbar .laps-timeline .event-theme {
background-color: #5cb85c;
}
@@ -75,8 +64,9 @@
position: absolute;
z-index: 100000;
display: block;
visibility: visible;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 12px;
font-weight: normal;
line-height: 1.4;
opacity: 0;
filter: alpha(opacity=0);
@@ -126,13 +116,15 @@
}
#wpadminbar .tooltip.top-left .tooltip-arrow {
bottom: 0;
left: 5px;
right: 5px;
margin-bottom: -5px;
border-width: 5px 5px 0;
border-top-color: #464646;
}
#wpadminbar .tooltip.top-right .tooltip-arrow {
bottom: 0;
right: 5px;
left: 5px;
margin-bottom: -5px;
border-width: 5px 5px 0;
border-top-color: #464646;
}
@@ -159,13 +151,15 @@
}
#wpadminbar .tooltip.bottom-left .tooltip-arrow {
top: 0;
left: 5px;
right: 5px;
margin-top: -5px;
border-width: 0 5px 5px;
border-bottom-color: #464646;
}
#wpadminbar .tooltip.bottom-right .tooltip-arrow {
top: 0;
right: 5px;
left: 5px;
margin-top: -5px;
border-width: 0 5px 5px;
border-bottom-color: #464646;
}
@@ -177,3 +171,4 @@
line-height: 20px;
text-align: left;
}
/*# sourceMappingURL=laps.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["laps.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/progress-bars.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/mixins/vendor-prefixes.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/tooltip.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/variables.less","C:/server/www/dev/wp-content/plugins/laps/vendor/twbs/bootstrap/less/mixins/opacity.less"],"names":[],"mappings":"AAKA,WAEC,mBAEC;EACC,cAAA;EACA,UAAA;EACA,eAAA;EACA,QAAA;;AARH,WAEC,mBASC;EACC,UAAA;;AAZH,WAgBC;EAEC,eAAA;;AAEA,WAJD,0BAIE;EACA,6BAAA;;AArBH,WAgBC,0BAQC;EACC,aAAA;;AAzBH,WA6BC;ECRC,gBAAA;EACA,YAAA;EACA,mBAAA;EACA,yBAAA;EACA,kBAAA;ECsCA,sDAAA;EACQ,8CAAA;EFjCR,aAAA;EACA,kBAAA;;AAhCF,WA6BC,eAKC;ECHA,WAAA;EACA,SAAA;EACA,YAAA;EACA,eAAA;EACA,iBAAA;EACA,cAAA;EACA,kBAAA;EACA,yBAAA;ECyBA,sDAAA;EACQ,8CAAA;EAyHR,mCAAA;EACK,8BAAA;EACG,2BAAA;EFvJP,kBAAA;EACA,8BAAA;EACA,cAAA;;AAtCH,WA6BC,eAYC;EACC,yBAAA;;AA1CH,WA6BC,eAeC;EACC,yBAAA;;AA7CH,WA6BC,eAkBC;EACC,yBAAA;;AAhDH,WA6BC,eAqBC;EACC,yBAAA;;AAnDH,WA6BC,eAwBC;EACC,yBAAA;;AAtDH,WGCA;EACE,kBAAA;EACA,eAAA;EACA,cAAA;EAEA,aCiCwB,8CDjCxB;EACA,eAAA;EACA,mBAAA;EACA,gBAAA;EEXA,UAAA;EAGA,wBAAA;;AFWA,WAXF,SAWG;EEdD,YAAA;EAGA,yBAAA;;AFYA,WAZF,SAYG;EAAU,gBAAA;EAAmB,cAAA;;AAC9B,WAbF,SAaG;EAAU,gBAAA;EAAmB,cAAA;;AAC9B,WAdF,SAcG;EAAU,eAAA;EAAmB,cAAA;;AAC9B,WAfF,SAeG;EAAU,iBAAA;EAAmB,cAAA;;AHhBhC,WGoBA;EACE,gBAAA;EACA,gBAAA;EACA,cAAA;EACA,kBAAA;EACA,qBAAA;EACA,yBAAA;EACA,kBAAA;;AH3BF,WG+BA;EACE,kBAAA;EACA,QAAA;EACA,SAAA;EACA,yBAAA;EACA,mBAAA;;AAIA,WADF,SACG,IAAK;EACJ,SAAA;EACA,SAAA;EACA,iBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WARF,SAQG,SAAU;EACT,SAAA;EACA,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WAfF,SAeG,UAAW;EACV,SAAA;EACA,SAAA;EACA,mBAAA;EACA,uBAAA;EACA,yBAAA;;AAEF,WAtBF,SAsBG,MAAO;EACN,QAAA;EACA,OAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;;AAEF,WA7BF,SA6BG,KAAM;EACL,QAAA;EACA,QAAA;EACA,gBAAA;EACA,2BAAA;EACA,0BAAA;;AAEF,WApCF,SAoCG,OAAQ;EACP,MAAA;EACA,SAAA;EACA,iBAAA;EACA,uBAAA;EACA,4BAAA;;AAEF,WA3CF,SA2CG,YAAa;EACZ,MAAA;EACA,UAAA;EACA,gBAAA;EACA,uBAAA;EACA,4BAAA;;AAEF,WAlDF,SAkDG,aAAc;EACb,MAAA;EACA,SAAA;EACA,gBAAA;EACA,uBAAA;EACA,4BAAA;;AH9FJ,WA4DC,SAAQ;EK9DP,UAAA;EAGA,0BAAA;;ALDF,WAgEC;EACC,iBAAA;EACA,gBAAA","file":"laps.css"}
+1
View File
@@ -0,0 +1 @@
#wpadminbar #wp-admin-bar-laps .ab-sub-wrapper{min-width:90%;width:90%;position:fixed;left:5%}#wpadminbar #wp-admin-bar-laps .ab-submenu{padding:0}#wpadminbar #wp-admin-bar-laps_output{padding:0 10px}#wpadminbar #wp-admin-bar-laps_output:hover{background-color:transparent}#wpadminbar #wp-admin-bar-laps_output .ab-empty-item{display:none}#wpadminbar .laps-timeline{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);margin:6px 0;position:relative}#wpadminbar .laps-timeline .event{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#ffffff;text-align:center;background-color:#5bc0de;-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;position:absolute;border-left:1px solid #f5f5f5;min-width:2px}#wpadminbar .laps-timeline .event-theme{background-color:#5cb85c}#wpadminbar .laps-timeline .event-plugin{background-color:#428bca}#wpadminbar .laps-timeline .event-core{background-color:#f0ad4e}#wpadminbar .laps-timeline .event-query{background-color:#5bc0de}#wpadminbar .laps-timeline .event-http{background-color:#d9534f}#wpadminbar .tooltip{position:absolute;z-index:100000;display:block;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;font-size:12px;font-weight:normal;line-height:1.4;opacity:0;filter:alpha(opacity=0)}#wpadminbar .tooltip.in{opacity:0.9;filter:alpha(opacity=90)}#wpadminbar .tooltip.top{margin-top:-3px;padding:5px 0}#wpadminbar .tooltip.right{margin-left:3px;padding:0 5px}#wpadminbar .tooltip.bottom{margin-top:3px;padding:5px 0}#wpadminbar .tooltip.left{margin-left:-3px;padding:0 5px}#wpadminbar .tooltip-inner{max-width:300px;padding:3px 8px;color:#cccccc;text-align:center;text-decoration:none;background-color:#464646;border-radius:4px}#wpadminbar .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}#wpadminbar .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#464646}#wpadminbar .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#464646}#wpadminbar .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#464646}#wpadminbar .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#464646}#wpadminbar .tooltip.in{opacity:1;filter:alpha(opacity=100)}#wpadminbar .tooltip-inner{line-height:20px;text-align:left}
+82 -54
View File
@@ -1,15 +1,13 @@
/* ========================================================================
* Bootstrap: tooltip.js v3.2.0
* Bootstrap: tooltip.js v3.3.4
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
// modified to use lapstooltip as plugin name
+function ($) {
'use strict';
@@ -17,17 +15,19 @@
// ===============================
var Tooltip = function (element, options) {
this.type =
this.options =
this.enabled =
this.timeout =
this.hoverState =
this.type = null
this.options = null
this.enabled = null
this.timeout = null
this.hoverState = null
this.$element = null
this.init('lapstooltip', element, options)
this.init('tooltip', element, options)
}
Tooltip.VERSION = '3.2.0'
Tooltip.VERSION = '3.3.4'
Tooltip.TRANSITION_DURATION = 150
Tooltip.DEFAULTS = {
animation: true,
@@ -52,6 +52,10 @@
this.options = this.getOptions(options)
this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
if (this.$element[0] instanceof document.constructor && !this.options.selector) {
throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
}
var triggers = this.options.trigger.split(' ')
for (var i = triggers.length; i--;) {
@@ -105,6 +109,11 @@
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
if (self && self.$tip && self.$tip.is(':visible')) {
self.hoverState = 'in'
return
}
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
@@ -147,7 +156,7 @@
if (this.hasContent() && this.enabled) {
this.$element.trigger(e)
var inDom = $.contains(document.documentElement, this.$element[0])
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
if (e.isDefaultPrevented() || !inDom) return
var that = this
@@ -183,13 +192,13 @@
if (autoPlace) {
var orgPlacement = placement
var $parent = this.$element.parent()
var parentDim = this.getPosition($parent)
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement
$tip
@@ -202,14 +211,17 @@
this.applyPlacement(calculatedOffset, placement)
var complete = function () {
var prevHoverState = that.hoverState
that.$element.trigger('shown.bs.' + that.type)
that.hoverState = null
if (prevHoverState == 'out') that.leave(that)
}
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
}
}
@@ -256,16 +268,18 @@
if (delta.left) offset.left += delta.left
else offset.top += delta.top
var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowPosition = delta.left ? 'left' : 'top'
var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
var isVertical = /top|bottom/.test(placement)
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
$tip.offset(offset)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
this.arrow()
.css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
.css(isVertical ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
@@ -276,16 +290,17 @@
$tip.removeClass('fade in top bottom left right')
}
Tooltip.prototype.hide = function () {
Tooltip.prototype.hide = function (callback) {
var that = this
var $tip = this.tip()
var $tip = $(this.$tip)
var e = $.Event('hide.bs.' + this.type)
this.$element.removeAttr('aria-describedby')
function complete() {
if (that.hoverState != 'in') $tip.detach()
that.$element.trigger('hidden.bs.' + that.type)
that.$element
.removeAttr('aria-describedby')
.trigger('hidden.bs.' + that.type)
callback && callback()
}
this.$element.trigger(e)
@@ -294,10 +309,10 @@
$tip.removeClass('in')
$.support.transition && this.$tip.hasClass('fade') ?
$.support.transition && $tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(150) :
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
complete()
this.hoverState = null
@@ -318,13 +333,20 @@
Tooltip.prototype.getPosition = function ($element) {
$element = $element || this.$element
var el = $element[0]
var isBody = el.tagName == 'BODY'
return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
width: isBody ? $(window).width() : $element.outerWidth(),
height: isBody ? $(window).height() : $element.outerHeight()
}, isBody ? { top: 0, left: 0 } : $element.offset())
var elRect = el.getBoundingClientRect()
if (elRect.width == null) {
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
return $.extend({}, elRect, scroll, outerDims, elOffset)
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
@@ -388,14 +410,6 @@
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
}
Tooltip.prototype.validate = function () {
if (!this.$element[0].parentNode) {
this.hide()
this.$element = null
this.options = null
}
}
Tooltip.prototype.enable = function () {
this.enabled = true
}
@@ -422,8 +436,11 @@
}
Tooltip.prototype.destroy = function () {
var that = this
clearTimeout(this.timeout)
this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
})
}
@@ -433,27 +450,38 @@
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.lapstooltip')
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data && option == 'destroy') return
if (!data) $this.data('bs.lapstooltip', (data = new Tooltip(this, options)))
if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.lapstooltip
var old = $.fn.tooltip
$.fn.lapstooltip = Plugin
$.fn.lapstooltip.Constructor = Tooltip
$.fn.tooltip = Plugin
$.fn.tooltip.Constructor = Tooltip
// TOOLTIP NO CONFLICT
// ===================
$.fn.lapstooltip.noConflict = function () {
$.fn.lapstooltip = old
$.fn.tooltip.noConflict = function () {
$.fn.tooltip = old
return this
}
}(jQuery);
jQuery.fn.lapstooltip = jQuery.fn.tooltip.noConflict();
jQuery(document).ready(function () {
jQuery(".laps-timeline .event").lapstooltip({
container: '#wpadminbar',
placement: 'bottom',
html : true,
animation: false
});
});
+5
View File
@@ -0,0 +1,5 @@
+function(t){'use strict';var e=function(t,e){this.type=null;this.options=null;this.enabled=null;this.timeout=null;this.hoverState=null;this.t$=null;this.init('tooltip',t,e)};e.VERSION='3.3.4';e.TRANSITION_DURATION=150;e.DEFAULTS={animation:!0,placement:'top',selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:'hover focus',title:'',delay:0,html:!1,container:!1,viewport:{selector:'body',padding:0}};e.prototype.init=function(e,i,s){this.enabled=!0;this.type=e;this.t$=t(i);this.options=this.getOptions(s);this.o$=this.options.viewport&&t(this.options.viewport.selector||this.options.viewport);if(this.t$[0]instanceof document.constructor&&!this.options.selector){throw new Error('`selector` option must be specified when initializing '+this.type+' on the window.document object!')};var r=this.options.trigger.split(' ');for(var n=r.length;n--;){var o=r[n];if(o=='click'){this.t$.on('click.'+this.type,this.options.selector,t.proxy(this.toggle,this))}
else if(o!='manual'){var a=o=='hover'?'mouseenter':'focusin',l=o=='hover'?'mouseleave':'focusout';this.t$.on(a+'.'+this.type,this.options.selector,t.proxy(this.enter,this));this.t$.on(l+'.'+this.type,this.options.selector,t.proxy(this.leave,this))}};this.options.selector?(this.i$=t.extend({},this.options,{trigger:'manual',selector:''})):this.fixTitle()};e.prototype.getDefaults=function(){return e.DEFAULTS};e.prototype.getOptions=function(e){e=t.extend({},this.getDefaults(),this.t$.data(),e);if(e.delay&&typeof e.delay=='number'){e.delay={show:e.delay,hide:e.delay}};return e};e.prototype.getDelegateOptions=function(){var e={};var i=this.getDefaults();this.i$&&t.each(this.i$,function(t,o){if(i[t]!=o)e[t]=o});return e};e.prototype.enter=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data('bs.'+this.type);if(i&&i.e$&&i.e$.is(':visible')){i.hoverState='in';return};if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)};clearTimeout(i.timeout);i.hoverState='in';if(!i.options.delay||!i.options.delay.show)return i.show();i.timeout=setTimeout(function(){if(i.hoverState=='in')i.show()},i.options.delay.show)};e.prototype.leave=function(e){var i=e instanceof this.constructor?e:t(e.currentTarget).data('bs.'+this.type);if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)};clearTimeout(i.timeout);i.hoverState='out';if(!i.options.delay||!i.options.delay.hide)return i.hide();i.timeout=setTimeout(function(){if(i.hoverState=='out')i.hide()},i.options.delay.hide)};e.prototype.show=function(){var u=t.Event('show.bs.'+this.type);if(this.hasContent()&&this.enabled){this.t$.trigger(u);var d=t.contains(this.t$[0].ownerDocument.documentElement,this.t$[0]);if(u.isDefaultPrevented()||!d)return;var s=this,o=this.tip(),c=this.getUID(this.type);this.setContent();o.attr('id',c);this.t$.attr('aria-describedby',c);if(this.options.animation)o.addClass('fade');var i=typeof this.options.placement=='function'?this.options.placement.call(this,o[0],this.t$[0]):this.options.placement,f=/\s?auto?\s?/i,h=f.test(i);if(h)i=i.replace(f,'')||'top';o.detach().css({top:0,left:0,display:'block'}).addClass(i).data('bs.'+this.type,this);this.options.container?o.appendTo(this.options.container):o.insertAfter(this.t$);var n=this.getPosition(),a=o[0].offsetWidth,l=o[0].offsetHeight;if(h){var g=i,y=this.options.container?t(this.options.container):this.t$.parent(),r=this.getPosition(y);i=i=='bottom'&&n.bottom+l>r.bottom?'top':i=='top'&&n.top-l<r.top?'bottom':i=='right'&&n.right+a>r.width?'left':i=='left'&&n.left-a<r.left?'right':i;o.removeClass(g).addClass(i)};var v=this.getCalculatedOffset(i,n,a,l);this.applyPlacement(v,i);var p=function(){var t=s.hoverState;s.t$.trigger('shown.bs.'+s.type);s.hoverState=null;if(t=='out')s.leave(s)};t.support.transition&&this.e$.hasClass('fade')?o.one('bsTransitionEnd',p).emulateTransitionEnd(e.TRANSITION_DURATION):p()}};e.prototype.applyPlacement=function(e,o){var i=this.tip(),u=i[0].offsetWidth,p=i[0].offsetHeight,r=parseInt(i.css('margin-top'),10),l=parseInt(i.css('margin-left'),10);if(isNaN(r))r=0;if(isNaN(l))l=0;e.top=e.top+r;e.left=e.left+l;t.offset.setOffset(i[0],t.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},e),0);i.addClass('in');var h=i[0].offsetWidth,n=i[0].offsetHeight;if(o=='top'&&n!=p){e.top=e.top+p-n};var s=this.getViewportAdjustedDelta(o,e,h,n);if(s.left)e.left+=s.left;else e.top+=s.top;var a=/top|bottom/.test(o),f=a?s.left*2-u+h:s.top*2-p+n,c=a?'offsetWidth':'offsetHeight';i.offset(e);this.replaceArrow(f,i[0][c],a)};e.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?'left':'top',50*(1-t/e)+'%').css(i?'top':'left','')};e.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find('.tooltip-inner')[this.options.html?'html':'text'](e);t.removeClass('fade in top bottom left right')};e.prototype.hide=function(i){var s=this,o=t(this.e$),r=t.Event('hide.bs.'+this.type);function n(){if(s.hoverState!='in')o.detach();s.t$.removeAttr('aria-describedby').trigger('hidden.bs.'+s.type);i&&i()};this.t$.trigger(r);if(r.isDefaultPrevented())return;o.removeClass('in');t.support.transition&&o.hasClass('fade')?o.one('bsTransitionEnd',n).emulateTransitionEnd(e.TRANSITION_DURATION):n();this.hoverState=null;return this};e.prototype.fixTitle=function(){var t=this.t$;if(t.attr('title')||typeof(t.attr('data-original-title'))!='string'){t.attr('data-original-title',t.attr('title')||'').attr('title','')}};e.prototype.hasContent=function(){return this.getTitle()};e.prototype.getPosition=function(e){e=e||this.t$;var s=e[0],o=s.tagName=='BODY',i=s.getBoundingClientRect();if(i.width==null){i=t.extend({},i,{width:i.right-i.left,height:i.bottom-i.top})};var n=o?{top:0,left:0}:e.offset();var a={scroll:o?document.documentElement.scrollTop||document.body.scrollTop:e.scrollTop()};var r=o?{width:t(window).width(),height:t(window).height()}:null;retuLine truncated
else if(r>e.top+e.height){o.top=e.top+e.height-r}}
else{var p=i.left-s,a=i.left+s+n;if(p<e.left){o.left=e.left-p}
else if(a>e.width){o.left=e.left+e.width-a}};return o};e.prototype.getTitle=function(){var i,e=this.t$,t=this.options;i=e.attr('data-original-title')||(typeof t.title=='function'?t.title.call(e[0]):t.title);return i};e.prototype.getUID=function(t){do t+=~~(Math.random()*1000000);while(document.getElementById(t))return t};e.prototype.tip=function(){return(this.e$=this.e$||t(this.options.template))};e.prototype.arrow=function(){return(this.s$=this.s$||this.tip().find('.tooltip-arrow'))};e.prototype.enable=function(){this.enabled=!0};e.prototype.disable=function(){this.enabled=!1};e.prototype.toggleEnabled=function(){this.enabled=!this.enabled};e.prototype.toggle=function(e){var i=this;if(e){i=t(e.currentTarget).data('bs.'+this.type);if(!i){i=new this.constructor(e.currentTarget,this.getDelegateOptions());t(e.currentTarget).data('bs.'+this.type,i)}};i.tip().hasClass('in')?i.leave(i):i.enter(i)};e.prototype.destroy=function(){var t=this;clearTimeout(this.timeout);this.hide(function(){t.t$.off('.'+t.type).removeData('bs.'+t.type)})};function i(i){return this.each(function(){var s=t(this),o=s.data('bs.tooltip'),n=typeof i=='object'&&i;if(!o&&/destroy|hide/.test(i))return;if(!o)s.data('bs.tooltip',(o=new e(this,n)));if(typeof i=='string')o[i]()})};var o=t.fn.tooltip;t.fn.tooltip=i;t.fn.tooltip.Constructor=e;t.fn.tooltip.noConflict=function(){t.fn.tooltip=o;return this}}(jQuery);jQuery.fn.lapstooltip=jQuery.fn.tooltip.noConflict();jQuery(document).ready(function(){jQuery('.laps-timeline .event').lapstooltip({container:'#wpadminbar',placement:'bottom',html:!0,animation:!1})});
+11
View File
@@ -0,0 +1,11 @@
jQuery.fn.lapstooltip = jQuery.fn.tooltip.noConflict();
jQuery(document).ready(function () {
jQuery(".laps-timeline .event").lapstooltip({
container: '#wpadminbar',
placement: 'bottom',
html : true,
animation: false
});
});
+3 -2
View File
@@ -4,7 +4,7 @@ Plugin Name: Laps
Plugin URI: https://github.com/Rarst/laps
Description: Light WordPress profiler.
Author: Andrey "Rarst" Savchenko
Version:
Version: 1.3.2
Author URI: http://www.rarst.net/
Text Domain: laps
Domain Path: /lang
@@ -29,7 +29,8 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
DEALINGS IN THE SOFTWARE.
*/
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) )
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
require __DIR__ . '/vendor/autoload.php';
}
Rarst\Laps\Laps::on_load();
+12 -1
View File
@@ -14,12 +14,23 @@ class Core_Events extends Laps_Events {
$stops = array();
$stops['plugins_loaded'][20] = array(
$stops['plugins_loaded'][ - 2 ] = array(
'action' => 'stop',
'event' => 'Plugins Load',
'category' => 'plugin',
);
$stops['plugins_loaded'][ - 1 ] = array(
'event' => 'Plugins Loaded Hook',
'category' => 'plugin',
);
$stops['plugins_loaded'][20] = array(
'action' => 'stop',
'event' => 'Plugins Loaded Hook',
'category' => 'plugin',
);
$stops['setup_theme'][0] = array(
'event' => 'Themes Load',
'category' => 'theme',
+1 -1
View File
@@ -14,7 +14,7 @@ class Hybrid_Events extends Laps_Events {
*/
protected function is_applicable() {
return defined( 'HYBRID_VERSION' );
return defined( 'HYBRID_VERSION' ) && function_exists( 'hybrid_get_prefix' );
}
/**
+19 -36
View File
@@ -102,7 +102,11 @@ class Laps {
)
);
self::$stopwatch->$event['action']( $event['event'], $event['category'] );
if ( 'stop' === $event['action'] && ! self::$stopwatch->isStarted( $event['event'] ) ) {
return $input;
}
self::$stopwatch->{$event['action']}( $event['event'], $event['category'] );
return $input;
}
@@ -162,13 +166,13 @@ class Laps {
}
/**
* When theme is done possibly add theme-specific events.
* When theme is done possibly add vendor-specific events.
*/
static function after_setup_theme() {
foreach ( array( 'THA', 'Hybrid', 'Genesis', 'Thematic' ) as $theme ) {
foreach ( array( 'THA', 'Hybrid', 'Genesis', 'Thematic', 'Yoast' ) as $vendor ) {
$class = "Rarst\\Laps\\{$theme}_Events";
$class = "Rarst\\Laps\\{$vendor}_Events";
/** @var Laps_Events $events */
$events = new $class;
self::add_events( $events->get() );
@@ -180,36 +184,20 @@ class Laps {
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_scripts' ) );
add_action( 'admin_bar_menu', array( __CLASS__, 'admin_bar_menu' ), 100 );
add_action( 'wp_print_footer_scripts', array( __CLASS__, 'print_footer_scripts' ), 11 );
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_footer_scripts' ), 11 );
}
static function enqueue_scripts() {
wp_register_script( 'laps-tooltip', plugins_url( 'js/tooltip.js', __DIR__ ), array( 'jquery' ), '3.0.2', true );
wp_register_style( 'laps', plugins_url( 'css/laps.css', __DIR__ ) );
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
wp_register_script( 'laps', plugins_url( "js/laps{$suffix}.js", __DIR__ ), array( 'jquery' ), '3.3.1', true );
wp_register_style( 'laps', plugins_url( "css/laps{$suffix}.css", __DIR__ ) );
if ( is_admin_bar_showing() ) {
wp_enqueue_script( 'laps-tooltip' );
wp_enqueue_script( 'laps' );
wp_enqueue_style( 'laps' );
}
}
static function print_footer_scripts() {
if ( wp_script_is( 'laps-tooltip', 'done' ) ) {
?>
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery(".laps-timeline .event").lapstooltip({
container: '#wpadminbar', placement: 'bottom', html: true, animation: false
// , trigger: 'click'
});
});
</script><?php
}
}
/**
* Render interface and add to the toolbar.
*
@@ -226,6 +214,7 @@ class Laps {
$mustache = new \Mustache_Engine(
array(
'loader' => new \Mustache_Loader_FilesystemLoader( dirname( __DIR__ ) . '/views' ),
'cache' => new Mustache_Cache_FrozenCache( dirname( __DIR__ ) . '/views/cache' ),
)
);
@@ -245,7 +234,7 @@ class Laps {
$width = round( $duration / $total * 100, 2 );
$category = $event->getCategory();
if ( 'http' == $category ) {
if ( 'http' === $category ) {
$http_data[] = compact( 'name', 'offset', 'duration', 'width', 'category' );
continue;
}
@@ -271,7 +260,7 @@ class Laps {
$offset = round( ( $query_start - $start ) / $total * 100, 2 );
// if query is indistinguishably close to previous then stack it
if ( $offset == $last_offset ) {
if ( $offset === $last_offset ) {
$key = count( $query_data ) - 1;
$query_data[ $key ]['sql'] .= '<br />' . $sql;
@@ -290,8 +279,6 @@ class Laps {
}
}
// !d( self::$query_starts, $wpdb->queries, $query_data );
$html = $mustache->render(
'laps',
array(
@@ -303,19 +290,15 @@ class Laps {
)
);
$wp_admin_bar->add_node(
array(
$wp_admin_bar->add_node( array(
'id' => 'laps',
'title' => sprintf( 'Lap: %ss', round( $total / 1000, 3 ) ),
)
);
) );
$wp_admin_bar->add_node(
array(
$wp_admin_bar->add_node( array(
'id' => 'laps_output',
'parent' => 'laps',
'meta' => array( 'html' => $html ),
)
);
) );
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Rarst\Laps;
/**
* Implements read-only filesystem cache
*/
class Mustache_Cache_FrozenCache extends \Mustache_Cache_FilesystemCache {
/**
* Cache and load a compiled Mustache_Template class.
*
* @param string $key
* @param string $value
*
* @return void
*/
public function cache( $key, $value ) {
$this->log(
\Mustache_Logger::WARNING,
'Read only cache file missing, evaluating "{className}" class at runtime',
array( 'className' => $key )
);
eval( '?>' . $value );
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace Rarst\Laps;
/**
* Events for Yoast plugins
*/
class Yoast_Events extends Laps_Events {
/**
* @return bool
*/
protected function is_applicable() {
return class_exists( 'WPSEO_Frontend' );
}
/**
* @return array
*/
public function get_events() {
$stops = array();
$stops['wpseo_head'][1] = array(
'event' => 'WP SEO head hook',
'category' => 'plugin',
);
$stops['wpseo_head'][100] = array(
'action' => 'stop',
'event' => 'WP SEO head hook',
'category' => 'plugin',
);
return $stops;
}
}
@@ -0,0 +1,241 @@
<?php
class __Mustache_37c708633787b0bcaf1bd7b4adc8b13a extends Mustache_Template
{
private $lambdaHelper;
public function renderInternal(Mustache_Context $context, $indent = '')
{
$this->lambdaHelper = new Mustache_LambdaHelper($this->mustache, $context);
$buffer = '';
$newContext = array();
$buffer .= $indent . '<div class="laps-timeline">
';
// 'events' section
$value = $context->find('events');
$buffer .= $this->section83708baddd3627fe4d26675ddf7eaeb5($context, $indent, $value);
$buffer .= $indent . '</div>
';
$buffer .= $indent . '
';
// 'savequeries' section
$value = $context->find('savequeries');
$buffer .= $this->section9756eb1d93d100052bdb80ee49b09ad6($context, $indent, $value);
$buffer .= $indent . '
';
// 'savehttp' section
$value = $context->find('savehttp');
$buffer .= $this->section3669ef98d4f6390c8df9645c96a328ee($context, $indent, $value);
return $buffer;
}
private function section83708baddd3627fe4d26675ddf7eaeb5(Mustache_Context $context, $indent, $value)
{
$buffer = '';
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" data-toggle="tooltip" title="{{name}} - {{duration}} ms - {{memory}} MB" style="width:{{width}}%; left:{{offset}}%;"></div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" data-toggle="tooltip" title="';
$value = $this->resolveValue($context->find('name'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms - ';
$value = $this->resolveValue($context->find('memory'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' MB" style="width:';
$value = $this->resolveValue($context->find('width'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;"></div>
';
$context->pop();
}
}
return $buffer;
}
private function section8dd7d0439d6fbb51dfb44aaa94780d5c(Mustache_Context $context, $indent, $value)
{
$buffer = '';
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" title="{{sql}}" style="width:{{width}}%; left:{{offset}}%;"></div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" title="';
$value = $this->resolveValue($context->find('sql'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" style="width:';
$value = $this->resolveValue($context->find('width'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;"></div>
';
$context->pop();
}
}
return $buffer;
}
private function section9756eb1d93d100052bdb80ee49b09ad6(Mustache_Context $context, $indent, $value)
{
$buffer = '';
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="laps-timeline">
{{#queries}}
<div class="event event-{{category}}" title="{{sql}}" style="width:{{width}}%; left:{{offset}}%;"></div>
{{/queries}}
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . '<div class="laps-timeline">
';
// 'queries' section
$value = $context->find('queries');
$buffer .= $this->section8dd7d0439d6fbb51dfb44aaa94780d5c($context, $indent, $value);
$buffer .= $indent . '</div>
';
$context->pop();
}
}
return $buffer;
}
private function sectionFb9cb3f90496dc38ba05f46e0ac2ad5d(Mustache_Context $context, $indent, $value)
{
$buffer = '';
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="event event-{{category}}" title="{{name}} - {{duration}} ms" style="width:{{width}}%; left:{{offset}}%;"></div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . ' <div class="event event-';
$value = $this->resolveValue($context->find('category'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '" title="';
$value = $this->resolveValue($context->find('name'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' - ';
$value = $this->resolveValue($context->find('duration'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= ' ms" style="width:';
$value = $this->resolveValue($context->find('width'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%; left:';
$value = $this->resolveValue($context->find('offset'), $context, $indent);
$buffer .= htmlspecialchars($value, 2, 'UTF-8');
$buffer .= '%;"></div>
';
$context->pop();
}
}
return $buffer;
}
private function section3669ef98d4f6390c8df9645c96a328ee(Mustache_Context $context, $indent, $value)
{
$buffer = '';
if (!is_string($value) && is_callable($value)) {
$source = '
<div class="laps-timeline">
{{#http}}
<div class="event event-{{category}}" title="{{name}} - {{duration}} ms" style="width:{{width}}%; left:{{offset}}%;"></div>
{{/http}}
</div>
';
$result = call_user_func($value, $source, $this->lambdaHelper);
if (strpos($result, '{{') === false) {
$buffer .= $result;
} else {
$buffer .= $this->mustache
->loadLambda((string) $result)
->renderInternal($context);
}
} elseif (!empty($value)) {
$values = $this->isIterable($value) ? $value : array($value);
foreach ($values as $value) {
$context->push($value);
$buffer .= $indent . '<div class="laps-timeline">
';
// 'http' section
$value = $context->find('http');
$buffer .= $this->sectionFb9cb3f90496dc38ba05f46e0ac2ad5d($context, $indent, $value);
$buffer .= $indent . '</div>
';
$context->pop();
}
}
return $buffer;
}
}