Compare commits

...

1525 Commits

Author SHA1 Message Date
ad66ef3dc5 Merge pull request #871 from cytopia/release/v1.11.0
Release/v1.11.0
2022-03-22 21:46:18 +01:00
907d6797ca Re-enable testing wordpress for PHP 8.0 and PHP 8.1 2022-03-22 15:17:20 +01:00
708253ebd9 Add support section 2022-03-22 15:16:31 +01:00
fe3c90f117 Fixes #867 Adminer 4.8.1 CSS issues 2022-03-22 10:54:08 +01:00
8666ca68bc Fix CI test output for Adminer Mongo 2022-03-22 10:51:01 +01:00
91da7d3f5b Refs #837 Update phpmyadmin to 5.1.3 2022-03-22 10:26:48 +01:00
5804546be4 Fix shellcheck errors for CI tests 2022-03-22 09:23:40 +01:00
39aae0501c Add MariaDB 10.8 to CI tests 2022-03-22 01:40:51 +01:00
eadafcf6ba Updated project files 2022-03-22 01:33:13 +01:00
7f3d37e606 Updated bind image 2022-03-22 01:26:05 +01:00
c87f18fe78 Update PHP-FPM images 2022-03-22 01:25:18 +01:00
d4b0be9ac4 Be more verbose during test startup 2022-03-18 15:00:45 +01:00
218ed79e14 Fixed array definition for PHP < 5.4 2022-03-18 15:00:04 +01:00
6a98ee4109 Update project files 2022-03-18 14:04:02 +01:00
d6337ccb51 #844 Update docs for HTTP/2 settings 2022-03-18 13:24:37 +01:00
4945ca2ccd Update README 2022-03-18 13:13:45 +01:00
ace31c89ed Fixes #854 pidof issue for rsyslog on arm64 2022-03-18 13:12:20 +01:00
81d2f7d02b Fixes #844 Allow to globally enable/disable HTTP/2 2022-03-18 13:10:12 +01:00
1bb408f16b Make PHP 8.1 the default 2022-03-18 13:09:25 +01:00
4e10d85de6 Make MariaDB 10.6 the default 2022-03-16 17:31:02 +01:00
349fa0ec73 Merge pull request #869 from cytopia/release/v1.10.5
Release/v1.10.5
2022-03-16 16:40:25 +01:00
4b3cc3f1e8 Update project files 2022-03-16 14:33:13 +01:00
be73b353eb Use updated version of mysql 2022-03-16 14:31:16 +01:00
a45748e1aa Use updated version of bind 2022-03-16 14:27:57 +01:00
31103f0040 Merge pull request #865 from cytopia/release/v1.10.4
Release v1.10.4
2022-02-15 16:11:49 +01:00
bdad47617c Adjust CI email test 2022-02-15 12:25:28 +01:00
52a42623bb Updated CHANGELOG 2022-02-15 12:10:04 +01:00
75f1d7f471 Made vhost error message more verbose 2022-02-15 12:09:20 +01:00
03eb46da99 Changed Intranet mail tester to using POST instead of GET for larger body size 2022-02-15 12:08:27 +01:00
dd85f5b1bb Fixed SSL-Cache Mutex on M1 CPU 2022-02-15 12:06:52 +01:00
fca58c22c6 Merge pull request #864 from cytopia/release/v1.10.3
Release v1.10.3
2022-02-04 19:13:08 +01:00
830549a905 Update README 2022-02-04 12:47:03 +01:00
015d66052e Adjust CHANGELOG 2022-02-04 11:05:05 +01:00
82a1d7c881 Adjust release date 2022-02-04 11:04:02 +01:00
7d346463c7 Adjust smoke tests 2022-02-04 11:03:00 +01:00
ae780388dc Update PHP images 2022-02-03 20:34:01 +01:00
422af8e916 Added missing mariadb entries into gitignore 2022-02-03 10:16:11 +01:00
3d3f716121 Added PHP 8.2 2022-02-03 10:15:54 +01:00
928d5a2475 Updated get-modules tests 2022-02-03 10:01:56 +01:00
9b37e3a307 Updated project files 2022-02-03 10:01:28 +01:00
682eaf82ee Merge pull request #863 from cytopia/release/v1.10.2
Release v1.10.2
2022-02-02 18:57:11 +01:00
38b96b7a08 Updated project files 2022-02-02 11:41:20 +01:00
94bf3c9dcf Updated PHP images 2022-02-02 11:40:50 +01:00
9272bfec92 Merge pull request #861 from cytopia/release/v1.10.1
Release v1.10.1
2022-01-30 20:20:53 +01:00
d57e72bc75 Update project files 2022-01-30 14:28:50 +01:00
bbc6a661ed Fixes #754 Be able to delete emails from control center 2022-01-30 14:27:08 +01:00
2ea5ff59e0 Fxies #830 Evaluate MASS_VHOST_SSL_GEN env var 2022-01-30 13:59:43 +01:00
ba6fd1e554 Merge pull request #860 from cytopia/release/v1.10.0
Release v1.10.0
2022-01-28 08:36:08 +01:00
fe67bdf6bb Harden CI tests 2022-01-27 17:30:00 +01:00
4a9c0b6d9f Update HTTPD images 2022-01-27 14:49:57 +01:00
855d98d895 Add Docker volumes for MariaDB 10.6 and 10.7 2022-01-27 12:37:47 +01:00
01b0ecdf20 Fixes #807 description in env-example 2022-01-27 08:41:55 +01:00
fe9e6264d9 Update PHP modules in README 2022-01-27 08:30:41 +01:00
55bb37c53b Update project files 2022-01-27 08:23:19 +01:00
a6894b7793 Add MariaDB conf anbd log dirs 2022-01-27 08:21:44 +01:00
0daa62cc02 Update comment about PHP 8.0 and 8.1 stability 2022-01-27 08:17:32 +01:00
38942fa168 Added MariaDB 10.6 and MariaDB 10.7 2022-01-27 08:15:46 +01:00
a0246b7a0e Update HTTPD images 2022-01-27 08:11:28 +01:00
b17f4600f4 Update PHP images 2022-01-27 08:11:12 +01:00
5f465abd61 Merge pull request #851 from felixmosh/fix-850
fix: show utf-8 mail body properly
2022-01-26 12:08:04 +01:00
61246b5151 Merge branch 'master' into fix-850 2022-01-26 10:01:31 +01:00
ca90af0fb0 Merge pull request #859 from cytopia/release/v1.9.3
Release v1.9.3
2022-01-25 20:14:49 +01:00
7bd6b34698 Update project files 2022-01-25 10:06:22 +01:00
2677422250 Update PHP images 2022-01-24 19:29:54 +01:00
200000cb5b Ensure documentation passes CI checks 2022-01-24 15:23:41 +01:00
8560267fdc Update MySQL Docker Images 2022-01-24 14:39:10 +01:00
8c13144d3e Update available PHP modules 2022-01-24 09:27:31 +01:00
2f8fc59dd9 Ensure PHP code is compatible to legacy versions 2022-01-24 09:15:52 +01:00
d9fb88058f Updated PHP Docker Images to 0.129 2022-01-24 08:39:23 +01:00
4c15e191a0 Merge branch 'master' into fix-850 2022-01-23 13:36:19 +01:00
249b132e58 Merge pull request #832 from Ernestopheles/patch-1
Update setup-auto-dns.rst
2022-01-23 13:35:44 +01:00
6e34d3b263 Merge pull request #843 from ericvanjohnson/patch-1
Update add-project-dns-entry-on-win.rst (grammar correction)
2022-01-23 13:33:17 +01:00
68bd88d304 Merge branch 'master' into patch-1 2022-01-23 13:32:39 +01:00
bfb4769e85 fix: show utf-8 mail body properly 2021-11-07 15:56:54 +02:00
23a6aed10d Merge pull request #817 from ulin-evgeny/patch
Fixed typos
2021-10-15 11:48:42 +02:00
0dfd63d7f9 Merge branch 'master' into patch 2021-10-15 11:48:31 +02:00
3804a3b6f3 Merge pull request #842 from ericp-mrel/fix-redis-args-parsing
Fix redis args parsing for password
2021-10-15 11:47:49 +02:00
9cfc69e5bb Update add-project-dns-entry-on-win.rst 2021-10-13 04:48:52 -07:00
56555e87a5 Adjust redis args regex to allow optional quotes. 2021-10-12 10:44:44 -05:00
5e90a3a35d Use preg_match_all to get redis password from args
This should fix the issue where preg_split was being used and would cause an error if the redis args variable didn't contain the --requirepass string and the WebGUI wouldn't load as a result.
2021-10-12 09:42:04 -05:00
54e17f5ec5 Update setup-auto-dns.rst
For me it has been unclear if prot 53 may not be in use in cobination to 127.0.0.1 or generally.
2021-08-24 17:48:52 +02:00
b5d19264de Fixed typos 2021-06-20 05:07:19 +03:00
f6bbdc72fd Merge pull request #814 from cytopia/release/v1.9.2
Release v1.9.2
2021-06-04 13:06:36 +02:00
2f9ba2e30a Release v1.9.2 2021-06-04 10:32:46 +02:00
fa0c8f5632 Merge pull request #787 from merlijnvanlent/master
Ability to view emails within the intranet dashboard.
2021-05-21 15:31:13 +02:00
64330b5b12 Merge branch 'master' into master 2021-05-21 10:50:26 +02:00
872340e14b Merge pull request #806 from Agnohendrix/patch-1
XDebug 3.0 Linux Docs
2021-05-21 10:48:21 +02:00
5eb2ee8ca0 Merge branch 'master' into master 2021-05-20 16:28:02 +02:00
aff86a6b15 Merge branch 'master' into patch-1 2021-05-20 15:48:25 +02:00
fb51eece98 Merge pull request #777 from cytopia/release/v1.9.1
Devilbox Release v1.9.1
2021-05-20 14:51:02 +02:00
6c438bb434 Updated Adminer to 4.8.1 2021-05-20 10:52:49 +02:00
9935780588 Update README 2021-05-20 00:12:10 +02:00
20cba7d773 Update CHANGELOG 2021-05-20 00:03:16 +02:00
353fa53d29 Updated php images to 0.125 2021-05-19 22:59:42 +02:00
f28e1ee4a4 Enable mysql binlog by default 2021-05-19 19:04:22 +02:00
fb390ac429 gitignore php-ini 8.1 dir 2021-05-19 19:03:56 +02:00
867327a8c3 Update project files 2021-05-19 16:06:53 +02:00
8ffd65a905 Upgrade sphinx deprecations 2021-05-19 16:05:45 +02:00
5a4574edb8 Remove Travis CI 2021-05-19 16:05:44 +02:00
dc350b00b5 Update CHANGELOG date 2021-05-19 16:05:43 +02:00
f4d492ea98 Update release date 2021-05-19 16:05:42 +02:00
c40c43c4ea Exclude shellcheck rule 2021-05-19 16:05:41 +02:00
d0585bb174 Update documentation 2021-05-19 16:05:40 +02:00
0b9d18cdf4 Adjust enabled PHP modules 2021-05-19 16:05:33 +02:00
ba42717f01 Update CHANGELOG 2021-05-19 16:05:29 +02:00
b4c3de9195 Update PHP images to 0.124 2021-05-19 16:05:25 +02:00
a0423ebd02 Adjust xdebug CI tests 2021-05-19 16:05:21 +02:00
06c2a7ac51 Update Available PHP modules in README 2021-05-19 16:05:17 +02:00
543e373b91 Added PHP Xdebug info page for intranet 2021-05-19 16:05:14 +02:00
3d0154f987 Docs: smaller headlines for PHP modules 2021-05-19 16:05:10 +02:00
715c6b3c83 Adjusted Xdebug 3.0 defaults 2021-05-19 16:05:06 +02:00
d8e728a6a4 Merge pull request #802 from llaville/patch-intranet
Patch intranet to fix issue 801
2021-05-19 16:04:34 +02:00
1d41fb025c Merge branch 'master' into patch-intranet 2021-05-19 16:01:18 +02:00
af98125279 Merge branch 'master' into patch-1 2021-05-18 08:39:16 +02:00
ab761eedba Merge pull request #783 from mhodge13/master
Kibana 6.6 and above uses ELASTICSEARCH_HOSTS
2021-05-17 20:36:00 +02:00
0058e0bd61 Merge branch 'master' into master 2021-05-17 20:34:25 +02:00
2dd3ec9dd0 Merge pull request #781 from kovacbb/patch-1
Update enable-varnish.rst
2021-05-17 20:33:47 +02:00
7f294735e7 Fixed wrong push 2021-05-05 15:55:44 +02:00
a07b3442f1 Updated XDebug Linux documentation for XDebug 3.0 2021-05-05 15:50:46 +02:00
db1be81471 Update compose/docker-compose.override.yml-elk 2021-04-19 18:10:43 +02:00
d5e463db60 Update compose/docker-compose.override.yml-all 2021-04-19 18:10:36 +02:00
83c0c672d4 avoid PHP Fatal Error when pgsql PHP module is not available 2021-04-19 17:27:20 +02:00
af68fb65f2 avoid PHP Fatal Error when mysqli PHP module is not available 2021-04-19 17:25:56 +02:00
f6c273d6c4 avoid PHP Fatal Error when memcache PHP modules are not available 2021-04-19 17:24:11 +02:00
46f5c48ba0 avoid PHP Fatal Error when redis PHP module is not available 2021-04-19 17:21:47 +02:00
6c18e8f112 avoid PHP Fatal Error when mongo PHP modules are not available 2021-04-19 17:20:00 +02:00
6807b83e6b typo error fixed in memcached info panel 2021-04-19 14:29:43 +00:00
01fb99ec1a Added custom shadowdom element to view emails
WIthout the styling leaking into the global styling.
2021-02-21 14:40:16 +01:00
56342426b3 Kibana 6.6 and above uses ELASTICSEARCH_HOSTS 2021-02-11 08:48:18 -06:00
87e710050f Update enable-varnish.rst
fix small typo
2021-02-04 22:49:29 +01:00
cdfb55ec2d Merge pull request #771 from alikon/patch-1
xdebug v3 info panel
2020-12-21 10:14:40 +01:00
7cad84f527 Update .devilbox/www/htdocs/xdebug.php
Co-authored-by: cytopia <cytopia@everythingcli.org>
2020-12-21 08:24:46 +01:00
e65685b604 with header and footer 2020-12-18 17:16:28 +01:00
7e08261602 moved to Info 2020-12-18 14:07:46 +01:00
30d23f0f6f move to Info 2020-12-18 14:06:57 +01:00
b5fca3f842 moved on Info 2020-12-18 14:06:38 +01:00
dd529d0a1a xdebug 3 info panel 2020-12-18 12:59:49 +01:00
a6863c5ceb xdebug v3 info panel 2020-12-18 12:58:17 +01:00
6dba0ce963 Merge pull request #766 from BrookeDot/patch-1
Capitalize p in WordPress
2020-12-13 17:17:36 +01:00
201925e0b2 Merge branch 'master' into patch-1 2020-12-13 13:07:31 +01:00
ffee650e60 Merge pull request #765 from cytopia/release/v1.9.0
Devilbox Release v1.9.0
2020-12-13 13:03:01 +01:00
59738601b2 Capitalize p in WordPress
This is a simple edit to capitalize the p in WordPress throughout this document
2020-12-12 16:37:03 -08:00
50ae11f95f Retry network tasks 2020-12-12 19:13:31 +01:00
09b8803f21 Adjust test and examples according to Xdebug 3.0 2020-12-12 19:04:35 +01:00
75aa5139e2 Sort correctly when updating modules 2020-12-12 18:14:15 +01:00
f9b4a9d9f4 Fix lint job 2020-12-12 17:54:32 +01:00
0151167635 Devilbox Release v1.9.0 2020-12-12 17:53:36 +01:00
9c6711c948 Update php images 2020-12-12 17:53:32 +01:00
22f5c945ef Fixes #761 missing varnish config env var 2020-12-12 17:53:28 +01:00
1b768425b2 Added checks for TLD_SUFFIX in check-config.sh 2020-12-12 17:53:24 +01:00
a05f3eea47 Merge pull request #760 from avierr/patch-1
Updated docs for Mac SSL
2020-12-01 19:12:20 +01:00
e3c1e18ae3 Update for Mac 2020-12-01 16:46:29 +00:00
a78bccfd33 Merge pull request #757 from cytopia/release/v1.8.3
Release v1.8.3
2020-11-22 17:08:56 +01:00
2679acc569 Fix symlink handling with watcherd 2020-11-22 14:36:13 +01:00
6b18f7b71d CI: wordpress: increase retries and be more verbose 2020-11-22 12:40:02 +01:00
df6ee3fb36 Intranet: show custom Httpd configuration files 2020-11-22 11:54:56 +01:00
fda37efc64 Check supervisor configs with check-config.sh 2020-11-22 11:13:04 +01:00
e9281c9b40 Bump versions 2020-11-22 10:57:37 +01:00
dfd3e27882 Fixes #753 handle symlinks with watcherd 2020-11-22 10:57:06 +01:00
8e7069f893 Fixes #692 Add custom supervisor configs 2020-11-22 10:56:08 +01:00
c96f740c39 check-config.sh: debug mode 2020-11-20 15:15:45 +01:00
fe54bbf714 check-config: custom configs 2020-11-20 15:09:21 +01:00
9660c37937 check-config.sh: verify LOCAL_LISTEN_ADDR 2020-11-20 14:46:29 +01:00
0d6ecf23e3 check-config.sh: check customizations 2020-11-20 14:35:53 +01:00
3a2dacf748 Fix shellcheck for check-config 2020-11-20 13:37:09 +01:00
467fc03640 Validate htdocs dir in check-config 2020-11-20 13:18:19 +01:00
7480eb4e08 Add project checks 2020-11-20 13:06:06 +01:00
f348fa7814 Fixes #751 check-config output duplication 2020-11-17 12:51:15 +01:00
b8055a175b Merge pull request #750 from cytopia/release/v1.8.2
Devilbox Release v1.8.2
2020-11-14 15:19:52 +01:00
9b58e2daa8 Fix typos 2020-11-14 15:17:38 +01:00
30e2b08c72 Fixes #547 Added link to official Contao Devilbox docs 2020-11-14 11:59:32 +01:00
1f0676de4a Fixes #707 Move Backups out of Devilbox directory 2020-11-14 11:51:33 +01:00
6735daaaeb Bump release 2020-11-14 10:49:50 +01:00
657ba28afd Fix entrypoint in MySQL image 2020-11-14 10:34:09 +01:00
14259518c6 check-config: allow paths to be outside Devilbox dir 2020-11-14 10:33:46 +01:00
d406eac805 Provide updating information 2020-11-14 10:33:22 +01:00
dfb2a1097d Various fixes on PHP-FPM images 2020-11-14 10:32:52 +01:00
8553a5645b Merge pull request #747 from cytopia/release/v1.8.1
Release v1.8.1
2020-11-12 19:22:21 +01:00
6e59572a51 CI: check-config.sh checks 2020-11-12 17:12:58 +01:00
bbf297a356 check-config.sh abort if .env file is not present 2020-11-12 17:12:58 +01:00
8a290af71c Ensure to check uid/gid with check-config 2020-11-12 17:12:58 +01:00
f2929f3d08 Merge branch 'master' into release/v1.8.1 2020-11-12 15:36:09 +01:00
4fb0d557a6 Merge pull request #734 from alexandredoria/patch-1
Enable remote_autostart as default on Xdebug configuration
2020-11-12 15:35:52 +01:00
d0776566a2 Merge branch 'master' into patch-1 2020-11-12 15:29:47 +01:00
254b76205c Update gitignore 2020-11-12 15:23:22 +01:00
d727835228 Replace tree with find command 2020-11-12 15:03:57 +01:00
760d1606c5 Adjust CI tests for PHP 8.(0|1) xdebug settings 2020-11-12 14:52:25 +01:00
5d476b9c32 Bump version 2020-11-12 14:44:59 +01:00
6465542af8 Fixes #746 xdebug config for PHP 8.0 and 8.1 2020-11-12 14:44:02 +01:00
686ad73b63 Ensure to check versions in check-config.sh 2020-11-12 14:39:14 +01:00
70695d179c Add hints to check-config.sh 2020-11-12 14:31:59 +01:00
039ffacaf7 Silence PHP warnings in phpmemcached and opcache GUIs 2020-11-12 14:20:42 +01:00
9367c9540a Add check-config.sh script for local troubleshooting 2020-11-12 14:19:49 +01:00
87fa92d931 Merge pull request #743 from cytopia/release/v1.8.0
Release v1.8.0
2020-11-09 09:46:22 +01:00
d655bea64f Fixed undefined var in integration tests 2020-11-08 15:52:32 +01:00
4acfa94639 Fix Adminer for PHP 8.0/8.1 2020-11-08 15:42:43 +01:00
2d5361891e Add integration tests for MariaDB 10.5 2020-11-08 15:42:00 +01:00
db58f3b1bb Disable Wordpress tests for PHP 8.0 and PHP 8.1 2020-11-08 14:46:02 +01:00
2dfb908fbf Fix phpPgAdmin for PHP 8.0 and PHP 8.1 2020-11-08 14:44:21 +01:00
20931a7d97 Fix missing config for phpMyAdmin 5.0.4 2020-11-08 14:09:11 +01:00
8fa4ea59c7 Fix shellcheck issues with tests 2020-11-08 13:59:20 +01:00
da12bccc29 Fix configs for phpMyAdmin 2020-11-08 13:55:44 +01:00
3e9bcec90b Add MariaDB 10.5 2020-11-08 13:52:33 +01:00
e5f93062ca Add PHP 8.1 conf directories 2020-11-08 13:47:02 +01:00
f37e9b2a58 Bump to minor release 2020-11-08 13:28:58 +01:00
156e36be56 Fix Adminer 4.7.7 2020-11-08 13:27:31 +01:00
6aca07a5b9 Update phpMyAdmin 2020-11-08 12:56:53 +01:00
530698aee2 Update documentation 2020-11-08 11:17:04 +01:00
9f647fa745 Adjust integration tests 2020-11-08 11:16:28 +01:00
8f510c7f6c Update Adminer from 4.7.5 to 4.7.7 2020-11-08 11:04:33 +01:00
d94cf193e3 Update env-example 2020-11-08 11:02:55 +01:00
d471794f72 Fix phpPgAdmin error reporting 2020-11-07 16:57:40 +01:00
9ff5006d1a Ensure phpRedmin works without login 2020-11-07 16:41:02 +01:00
9179683f18 Ensure backwards compatibility with phpPgAdmin 2020-11-07 16:15:32 +01:00
16a0f360bf Fix CHANGELOG 2020-11-07 15:56:37 +01:00
bca2a37723 #728 Updated phpPgAdmin from 7.12 to 7.13 2020-11-07 15:52:05 +01:00
e2806d147a Fix typo in version 2020-11-07 12:04:34 +01:00
9cefd120ef Add missing docker volumes 2020-11-07 11:54:35 +01:00
97d8602f19 Fix broken link in docs 2020-11-07 11:45:47 +01:00
2c8c8f2fa5 Update Readme 2020-11-07 11:34:52 +01:00
b9cf538dcf Update Changelog 2020-11-07 11:18:38 +01:00
f034dec17a Add latest available docker images 2020-11-07 11:17:59 +01:00
9ce7111587 Update integration tests 2020-11-07 11:17:13 +01:00
d5eca8a114 Update PHP images 2020-11-07 10:38:03 +01:00
81f344ee04 Enable remote_autostart on Xdebug configuration for Docker on Linux: Xdebug for Visual Studio Code
Normally is need to use a specific HTTP GET/POST variable to start remote debugging. When this setting is set to true, Xdebug will always attempt to start a remote debugging session and try to connect to  vscode-php-debug plugin client, even if the GET/POST/COOKIE variable was not present.

More information on 
https://xdebug.org/docs/all_settings
https://xdebug.org/docs/remote#browser_session
2020-10-09 12:58:03 -03:00
4b23dd6d6d Merge pull request #725 from cytopia/release/v1.7.2
Release v1.7.2
2020-09-18 10:18:39 +02:00
10952e80b2 Merge branch 'master' into release/v1.7.2 2020-09-17 17:28:48 +02:00
ae4514e1ca Merge pull request #726 from tyrann0us/patch-1
Fix typo docker-composer kil
2020-09-17 17:28:30 +02:00
0d1fe20cc4 Fix typo docker-composer kil 2020-09-17 13:47:21 +02:00
f67182f111 Added COMPOSER_MEMORY_LIMIT variable to php settings 2020-09-17 10:46:50 +02:00
4540afa507 CI Adjust drupal test 2020-09-16 15:19:46 +02:00
1868719479 Added new PHP images 2020-09-16 11:32:57 +02:00
3556873f19 Merge pull request #711 from cytopia/release/v1.7.1
Release v1.7.1
2020-08-09 18:32:42 +02:00
eafc56f5ab Update docker images 2020-08-09 16:30:18 +02:00
a10efca1c3 Refs #611, #700 Updating PHP images 2020-06-29 01:27:08 +02:00
8c931cdf56 Merge pull request #690 from cytopia/release/v1.7.0
Release v1.7.0
2020-03-25 09:41:40 +01:00
487b69331c Use reproducible linkcheck 2020-03-24 12:06:32 +01:00
6984d43ff9 Update version and Changelog 2020-03-24 09:31:12 +01:00
a097b5b4d8 Update Readme 2020-03-24 09:29:27 +01:00
0b118486b5 Update docs: available container 2020-03-24 09:29:26 +01:00
c73d5a711f Add Python Flask Compose files 2020-03-24 09:29:25 +01:00
78244371ca Ease linkcheck 2020-03-24 09:29:24 +01:00
a1fa4806e1 Add Python Flask logo 2020-03-24 09:29:22 +01:00
02e3f8cf6e Fix headlines 2020-03-24 09:29:21 +01:00
f7741d88f9 Documentation: Python Flask 2020-03-24 09:29:10 +01:00
bc16d8906e Merge pull request #689 from cytopia/release/v1.6.3
Release v1.6.3
2020-03-23 18:55:28 +01:00
fa6a91350c Fix Release number in Update info 2020-03-23 15:26:00 +01:00
d4e3b885da Update release date 2020-03-23 14:47:55 +01:00
68f34be368 Document new env variable 2020-03-23 14:47:33 +01:00
5679774a30 Default env variable to prevent .env misconfigurations 2020-03-23 11:40:19 +01:00
056bbfb057 Allow postgresql to start without a password 2020-03-23 11:31:43 +01:00
fb77920460 Bump version and update CHANGELOG 2020-03-22 16:15:32 +01:00
a377209a72 Updated HAProxy version 2020-03-22 16:15:28 +01:00
c1fbb9c2c4 Updated PHP-FPM versions 2020-03-22 16:15:24 +01:00
ca6f7f56ac Merge pull request #688 from mjherraiz/patch-1
Update docs to newest symfony version
2020-03-22 16:11:08 +01:00
163642aac7 Update php version in symfony example doc 2020-03-22 12:26:30 +01:00
37c82a334c Update docs to newest symfony version
The new symfony structure delete web folder and change it for more standart public folder.
Now diferents env are managed with and env file
2020-03-21 19:39:46 +01:00
844ca283bf Merge pull request #686 from ops-andy/docs/expressionengine
Add How To for ExpressionEngine cms
2020-03-20 06:22:03 +01:00
63de90415c more tweaks to setup-expressionengine and now passing builds 2020-03-19 13:23:07 -04:00
c67c66c8ef fixed underline error in setup-expressionengine 2020-03-19 12:45:53 -04:00
80b6582d91 Merge branch 'master' into docs/expressionengine 2020-03-19 12:44:20 -04:00
d68adcbb01 added more detail to install instrcutions and shortened curl link 2020-03-19 12:34:21 -04:00
112e24207b added back Joomla question in FAQ 2020-03-19 11:31:42 -04:00
17232a5eb4 added ExpressionEngine install docs 2020-03-19 11:27:04 -04:00
7d6c7a4aff Merge pull request #684 from bplus/patch-3
Minor spelling fix
2020-03-06 17:01:39 +01:00
a98c6146a4 Merge branch 'master' into patch-3 2020-03-06 17:01:32 +01:00
175e4d8d02 Merge pull request #683 from bplus/patch-1
Spelling fix: Apline to Alpine
2020-03-06 17:01:00 +01:00
c56243bb9d Merge branch 'master' into patch-1 2020-03-06 17:00:40 +01:00
e294e6f6cd Merge pull request #682 from bplus/patch-2
Update CONTRIBUTING.md
2020-03-06 17:00:10 +01:00
4691117100 Minor spelling fix 2020-03-05 14:16:47 -06:00
d104e4e9a5 Update CONTRIBUTING.md
Minor spelling fix.
2020-03-05 14:12:34 -06:00
8aabde1b5a Spelling fix: Apline to Alpine
Minor spelling error.
2020-03-05 14:11:06 -06:00
44bbf048ce Merge pull request #676 from llaville/fix_reverse-proxy_docs
Fix reverse proxy docs
2020-02-24 09:06:50 +01:00
84183c9688 fix typo error in desired DNS name 2020-02-19 17:06:16 +01:00
c05a74fd5f wrong dns record (probably copy/paste from setup-reverse-proxy-nodejs.rst) 2020-02-19 17:04:11 +01:00
0c5750b8bf Merge pull request #675 from alikon/patch-1
fix  year 2020 in changelog
2020-02-13 09:16:58 +01:00
886689ca64 year 2020 f 2020-02-10 12:23:28 +01:00
bfdd3ffbfc Merge pull request #671 from cytopia/release/v1.6.2
Release v1.6.2
2020-02-09 10:21:26 +01:00
3c12883ea1 Update modules in README 2020-02-08 18:45:04 +01:00
51281ef5a0 Release v1.6.2 2020-02-06 09:22:15 +01:00
bf140cf8cd Merge pull request #663 from cytopia/release/v1.6.1
Release v1.6.1
2020-01-05 17:43:52 +01:00
ed8639c636 Refs #662 Fix Symfony version display on Devilbox intranet 2020-01-05 17:18:07 +01:00
06830367c9 Fixes #662 Update to latest Symfony CLI 2020-01-05 15:26:56 +01:00
556b50d76c Merge pull request #661 from cytopia/readme-badges
Update badges
2020-01-05 02:18:27 +01:00
4d2839f6d5 Update badges 2020-01-05 02:19:47 +01:00
87fe2ba593 Merge pull request #660 from cytopia/fix-github-settings
Fix username
2020-01-05 01:39:49 +01:00
cd82fa74a7 Fix username 2020-01-05 01:41:25 +01:00
e48c8e96dc Merge pull request #659 from cytopia/release/v1.6.0
Release v1.6.0
2020-01-05 01:37:59 +01:00
f29d552dfa Fixes #378 Allow to mount local ssh dir into PHP container (r/o) 2020-01-04 22:15:50 +01:00
304fc86329 Fixes #615 Add tool: phpmd 2020-01-04 21:07:52 +01:00
d44905bfb5 Use IP address of PHP container for Apache/Nginx upstream to skip DNS lookup 2020-01-04 20:56:30 +01:00
1b9ef528d2 GitHub settings 2020-01-04 17:41:59 +01:00
4f97eae8fe Prepare Release v1.6.0 2020-01-04 17:06:29 +01:00
2e09f7f0f8 Refs #265 Make vhost ssl type configurable 2020-01-04 17:06:08 +01:00
6fa7a84bd3 Refs #642 Make email catch-all configurable 2020-01-04 17:03:42 +01:00
266c5b84a3 Ensure env file has equal spacing everywhere 2020-01-04 17:02:33 +01:00
b75aa9f2ab Merge pull request #658 from cytopia/fix-unbound-var
Fix unbound bash variable in CI tests
2020-01-04 15:44:27 +01:00
99163bd525 Fix unbound bash variable in CI tests 2020-01-04 15:45:54 +01:00
dada924b41 Merge pull request #657 from cytopia/release/v1.5.0
Release v1.5.0
2020-01-04 03:44:09 +01:00
75b6db7676 Refs #653 #643 add integration tests for MySQL/MariaDB/Percona images 2020-01-03 18:24:38 +01:00
f90b53c79a Fixes #654 Add Opcache Control Panel 2020-01-03 15:39:22 +01:00
7d1d3add5a Merge pull request #655 from cytopia/release/v1.4.0
Release v1.4.0
2020-01-02 18:32:22 +01:00
17735e09ce Adjust release date 2020-01-02 16:12:30 +01:00
ff143fe931 Fixes #265 HTTP to HTTPS redirect 2019-12-31 18:42:42 +01:00
72c7a7db02 Fixes #642 Fixes #614 Updated PHP Docker image 2019-12-31 18:41:13 +01:00
151246179d Refs #618 Update Compose override file with new version 2019-12-31 18:13:52 +01:00
6e27f83b4d Update Changelog 2019-12-31 17:47:57 +01:00
616fed6326 Fixes #618 Update Compose version to 2.3 2019-12-31 17:37:32 +01:00
0b9d127979 Merge pull request #650 from cytopia/update-vendors
Release v1.3.0
2019-12-28 23:40:17 +01:00
53e10a5a38 Fix error_reporting in phpMyAdmin 2019-12-28 22:20:32 +01:00
e3ce8593be Remove non-stable Redis image 2019-12-28 22:05:48 +01:00
e3da67d96d Adding Redis 6.0 2019-12-28 22:00:49 +01:00
4ae80c66aa Remove obsolete links from documentation 2019-12-28 21:27:15 +01:00
ada47bbd5b Ensure travis fails on errors 2019-12-28 21:26:49 +01:00
207b7ac7ad Add Adminer update instructions to changelog 2019-12-28 21:12:08 +01:00
25eac35991 Add phpMyAdmin 5.0.0 2019-12-28 21:02:28 +01:00
8eef4b05ec Update phpMyAdmin to 4.9.3 2019-12-28 20:55:21 +01:00
d8a84bb889 Fix failing tests for Adminer and PHP 8.0 2019-12-28 20:48:41 +01:00
4ac8eb17d2 Fix Adminer tests 2019-12-08 11:11:37 +01:00
e2930d2b4e Update version and Changelog 2019-12-08 08:17:19 +01:00
d6818a1470 Update phpMyAdmin to 4.9.2 2019-12-08 08:14:01 +01:00
914f32bc14 Fixes #626 Update Adminer to 4.7.5 2019-12-08 08:12:03 +01:00
9234730dd8 Merge pull request #648 from cytopia/docs
Build documentation in CI
2019-12-02 19:29:06 +01:00
921188a5b3 Build documentation in CI 2019-12-02 11:23:29 +01:00
bdf8eb7578 Merge pull request #647 from cytopia/release/v1.2.0
Release v1.2.0
2019-12-01 10:49:53 +01:00
dc9a30ed5f Fixes #592 sqlsrv connection problem 2019-11-30 23:15:35 +01:00
e6d0a1597f Reference more issues in Changelog 2019-11-30 23:02:31 +01:00
cf91371b61 Add Updating instructions 2019-11-30 22:59:42 +01:00
b07e2cb747 Cleanup docker-compose.yml 2019-11-30 22:53:21 +01:00
ca5dec2e57 Bump version and Changelog 2019-11-30 22:53:05 +01:00
ccea6e3814 Add latest MySQL images 2019-11-30 22:52:37 +01:00
ce4b340224 Fix #622 by adding httpd server with latest cert-gen version 2019-11-30 22:52:19 +01:00
31940fc22a Add latest PHP-FPM images 2019-11-30 22:51:15 +01:00
a7d3c53979 Make PHP 7.3 the default 2019-11-30 22:50:43 +01:00
44b146b824 Merge pull request #645 from cytopia/release/v1.1.0
Release v1.1.0
2019-11-24 22:16:46 +01:00
44b9611c94 Remove empty line from README.md 2019-11-24 16:15:01 +01:00
593dfbe31a Fix Wordpress CI check 2019-11-24 11:38:27 +01:00
a409c214c7 Do not change HTTP port when running from inside container 2019-11-24 10:37:49 +01:00
4daebaa325 Ensure vhost-gen config files match with upstream 2019-11-24 10:34:42 +01:00
967f282739 Adjust Changelog 2019-11-24 10:31:07 +01:00
182269fdf1 Update MongoDB images 2019-11-24 10:29:15 +01:00
57a1f335f6 Update PostgreSQL images 2019-11-24 10:25:29 +01:00
247530bcac Add GitHub Actions build badges 2019-11-24 10:24:04 +01:00
8f47af8bfb Exclude Apache 2.2 from static DirectoryIndex test 2019-11-24 10:06:37 +01:00
49d6c68bb5 Test Frameworks according to chosen PHP version 2019-11-24 10:02:12 +01:00
b318da24c6 Update version dates 2019-11-24 01:04:01 +01:00
3551c89311 Split GitHub Actions workflows 2019-11-24 01:02:51 +01:00
b5ed81e28a Fix Travis builds 2019-11-23 12:41:57 +01:00
57ff6da675 Fix unbound variable 2019-11-23 00:26:50 +01:00
c8de832210 Simplify tests 2019-11-23 00:02:17 +01:00
41493bc514 Test against wordpress 2019-11-22 23:11:34 +01:00
2f129611cc Fix unbound variable in tests 2019-11-22 10:41:25 +01:00
2744a39aec Adjust Travis CI checks 2019-11-22 08:56:49 +01:00
9cff9a1277 Update PHP image version 2019-11-22 08:49:26 +01:00
7301d581df Update Intranet version 2019-11-21 17:34:03 +01:00
c271734278 Update CHANGELOG 2019-11-21 17:33:34 +01:00
574a6cc183 Test all versions via GitHub Actions 2019-11-21 15:20:35 +01:00
5d9f396b14 Ensure Vendor login works 2019-11-21 14:55:16 +01:00
7ea5aa8aed Fixes #641 Adding latest version of phpPgAdmin 2019-11-21 13:35:45 +01:00
2a2167205a Make tests pass shellcheck 2019-11-21 12:44:35 +01:00
2b58cb5153 Fixes #644 Use PHP 7.4 with stable JPEG support 2019-11-20 12:01:20 +01:00
f4ddbfb15e Run CI steps even if previous ones failed 2019-11-18 00:58:24 +01:00
de89a170e7 php-fpm v0.92 2019-11-18 00:20:31 +01:00
2aacfeaaed Add integration tests via GitHub Actions 2019-11-18 00:17:10 +01:00
ace5d7c1fc Merge pull request #624 from nuno-andre/patch-1
Updates end-of-line for batch file
2019-11-02 19:53:34 +01:00
04e7c70b26 Updates end-of-line for batch file
Using *nix' `lf` line endings instead of `crlf` in Windows batch files can lead to [unexpected results](https://stackoverflow.com/questions/232651/why-the-system-cannot-find-the-batch-label-specified-is-thrown-even-if-label-e).
2019-08-27 19:26:53 +02:00
0543f2da92 Merge pull request #591 from cytopia/ngrok
Make Ngrok region configurable via NGROK_REGION env var
2019-06-11 08:58:53 +02:00
9b5e19cf41 Make Ngrok region configurable via NGROK_REGION env var 2019-06-10 19:00:02 +02:00
3dec841e88 Merge pull request #590 from cytopia/update-php-container
Fix #587 Use updated PHP images
2019-06-10 18:29:31 +02:00
3370934bb3 Bump version date 2019-06-10 16:46:24 +02:00
0a5327ac77 Reflect new modules in README 2019-06-10 16:46:10 +02:00
11c46cd9c0 Fix #587 Use updated PHP images 2019-06-10 16:40:44 +02:00
fdb6cffb3b Merge pull request #582 from cytopia/doc-updates
Bugfix updates
2019-05-21 16:46:56 +02:00
19e5d03fe0 Add yq to available tools 2019-05-21 09:45:06 +02:00
2294672403 Fix table valign 2019-05-21 09:24:57 +02:00
23a9b2b889 Prepare Bugfix release 2019-05-21 09:21:59 +02:00
15dcf8b350 Show OAuth modules in README 2019-05-21 09:09:05 +02:00
23ac8cde1a Bump version and update Changelog 2019-05-21 09:07:09 +02:00
c04750aa15 User latest PHP-FPM version 2019-05-20 23:53:53 +02:00
e6e5a1f8c6 Add Devilbox Flames to README 2019-05-18 15:49:41 +02:00
816aa75dab Merge pull request #578 from cytopia/update-php-container
Use latest php-fpm images
2019-05-16 00:28:41 +02:00
fb8499f645 Use latest php-fpm images 2019-05-12 15:47:09 +02:00
4be9018c2b Merge pull request #569 from cytopia/ci-tests
Re-enable Adminer tests for PHP 7.3
2019-04-28 18:48:28 +02:00
147fffb20d Re-enable Adminer tests for PHP 7.3 2019-04-28 18:48:02 +02:00
65b81ab2f8 Merge pull request #571 from cytopia/stale-bot
Protect WIP PR's from stale-bot
2019-04-28 13:59:49 +02:00
1eed5e2e4b Protect WIP PR's from stale-bot 2019-04-28 13:59:14 +02:00
204a8a0736 Merge pull request #570 from cytopia/stale-bot
Add stale bot to repository
2019-04-28 13:54:20 +02:00
94cb41fb1f Add stale bot to repository 2019-04-28 13:53:20 +02:00
6bc99d02b2 Merge pull request #568 from cytopia/update-php-container
Fix mods for PHP-FPM 8.0
2019-04-27 16:36:22 +02:00
e28f268098 567 Remove orphaned mentions of HOST_PATH_MYSQL_DATADIR 2019-04-27 12:59:09 +02:00
aef23ac4fd Fix link for iPhone app 2019-04-27 11:59:14 +02:00
1e8626bd87 Fix typo in documentation 2019-04-27 11:55:57 +02:00
e044f89ad0 Fix mods for PHP-FPM 8.0 2019-04-27 11:48:08 +02:00
7b853cdf79 Merge pull request #566 from cytopia/tools
Add tools: Angular CLI and Laravel Lumen
2019-04-22 12:27:05 +02:00
8fda181691 Refs #557 #559 Add tools: Angular CLI and Laravel Lumen 2019-04-20 12:40:41 +02:00
e91a7001b4 Merge pull request #565 from cytopia/docs-processwire
Documentation: Setup ProcessWire
2019-04-20 12:12:18 +02:00
e4068aac9f Documentation: Setup ProcessWire 2019-04-20 11:56:14 +02:00
5768c8505e Merge pull request #554 from cytopia/ci-tests
Fix CI tests for mail volume
2019-04-20 10:16:09 +02:00
fb8c378727 Fix CI tests for mail volume 2019-04-20 10:00:53 +02:00
6b7d6516e8 Merge pull request #563 from pniederlag/patch-1
follow TYPO3 CMS brand rules
2019-04-13 00:09:00 +02:00
3dc8d865fe follow TYPO3 CMS brand rules
TYPO3 brand is uppercased ;)
2019-04-12 15:57:46 +02:00
c0530520a1 Merge pull request #562 from cytopia/fix-docs
Fix docs
2019-04-12 09:07:13 +02:00
82206aed02 Update project information 2019-04-12 08:43:41 +02:00
6b663d2df5 Fixed typo in wordpress documentation 2019-04-12 08:43:14 +02:00
1a18c1891c Merge pull request #558 from pedrosanta/docs-version-tag-update
Update release tag on update docs
2019-04-09 08:34:36 +02:00
6d485dcc4f Update release tag on update docs 2019-04-05 16:55:58 +01:00
260c222209 Merge pull request #553 from groovenectar/patch-1
Typo + sentence change
2019-03-28 13:00:24 +01:00
6690610623 Typo + sentence change 2019-03-27 14:38:14 -04:00
ac040416cf Another note about git pull before changing branch (#552)
* Another note about git pull before changing branch

* Update checkout-different-devilbox-release.rst
2019-03-24 19:49:28 +01:00
b479bcaec9 Merge pull request #551 from pnoeric/patch-2
Added git pull
2019-03-24 19:48:12 +01:00
03afc32392 added info about git fetch 2019-03-24 18:08:41 +01:00
7a1dadf10c Added git pull 2019-03-24 13:04:45 +01:00
6da8f35cf7 Merge pull request #550 from cytopia/release/v1.0.1
Bugfix Release v1.0.1
2019-03-24 12:09:55 +01:00
d58b4f6035 Release preparation 2019-03-23 20:42:59 +01:00
f5e32c25a1 #373 Use fixed MySQL images which allow for custom configuration files 2019-03-23 20:40:29 +01:00
f45826edfd Deprecated wddx extension for PHP 7.4 and 8.0: https://wiki.php.net/rfc/deprecate-and-remove-ext-wddx 2019-03-23 20:37:28 +01:00
f94557062d Fixes #536 Add Vue cli 2019-03-23 20:36:41 +01:00
f2aa49b8cd Fixes #540 mysqldump-secure password substitution 2019-03-23 20:36:02 +01:00
acf3293692 #506 documentation: how to connect to MySQL and other services 2019-03-23 20:28:10 +01:00
5064effe89 #209 Fix Xdebug documentation for Docker for Windows 2019-03-23 20:03:53 +01:00
3cbbdb35b0 Merge pull request #416 from cytopia/release/v1.0.0
Devilbox Release v1.0.0
2019-03-19 08:55:19 +01:00
c2b8a53efc #500 docs troubleshooting mysql 2019-03-18 19:28:22 +01:00
2b521c9e71 Remove migration announcement 2019-03-18 19:15:46 +01:00
9e3da94edb Prepare Devilbox v1.0.0 release 2019-03-18 19:13:23 +01:00
1138c498c7 Update CHANGELOG 2019-03-18 19:10:22 +01:00
cfba16f887 Restore failed rebase 2019-03-18 19:10:18 +01:00
ef2f39f794 Clean up docker-compose.yml 2019-03-18 19:09:39 +01:00
f19a5d2ca2 Ensure mail uses a Docker volume 2019-03-18 19:09:38 +01:00
c582163951 Remove unecessary data dirs 2019-03-18 19:09:37 +01:00
c6542ad032 Update container versions 2019-03-18 19:09:36 +01:00
bb1b72d9af Ensure default values are used for mounted data directories as well 2019-03-18 19:09:35 +01:00
ba3dd31729 Refs #175, Refs #382 Use Docker volumes instead of data directories 2019-03-18 19:09:33 +01:00
0dc142e1e2 Merge pull request #546 from cytopia/docs-troubleshooting
Docs troubleshooting
2019-03-18 19:08:40 +01:00
8dbf591624 Update version date 2019-03-18 18:53:14 +01:00
ccdc3e07b8 Update changelog 2019-03-18 18:48:10 +01:00
3d8e08e398 #539 Troubleshoot 'no space left on device on MacOS' 2019-03-18 17:25:01 +01:00
ba58b846e2 #424 #473 #490 #500 #542 Document errors for starting MySQL 2019-03-18 15:16:06 +01:00
e4657f36e0 Merge pull request #538 from nickw108/master
Add blog post reference to documentation
2019-03-12 17:19:30 +01:00
558cd89e95 Add blog post reference to documentation 2019-03-12 12:38:59 +01:00
47f62d23b6 Merge pull request #537 from pnoeric/patch-1
Very small typo fix
2019-03-11 17:58:17 +01:00
c57dff5a44 Very small typo fix 2019-03-11 15:09:32 +01:00
4e429a97c3 Merge pull request #534 from cytopia/release/v0.15.0
Devilbox Release v0.15.0
2019-03-09 16:12:07 +01:00
fbc1b7f22c Prepare v0.15.0 Release 2019-03-09 15:10:59 +01:00
6de4a56fa3 Merge pull request #533 from cytopia/css-theme-docs
Fix CSS for code boxes
2019-03-09 12:49:05 +01:00
0c316eeef3 Fix CSS for code boxes 2019-03-09 12:48:30 +01:00
44f2e36071 Merge pull request #532 from cytopia/documentation-xdebug
Documentation for PHP Xdebug on Windows (indentation fix)
2019-03-09 12:17:42 +01:00
38332ba801 Fix #209 documentation for PHP Xdebug on Windows 2019-03-09 12:16:56 +01:00
c9f72e47c3 Merge pull request #531 from cytopia/documentation-xdebug
Fix documentation for PHP Xdebug on Windows
2019-03-09 12:12:31 +01:00
4e41e64308 Fix #209 documentation for PHP Xdebug on Windows 2019-03-09 12:10:27 +01:00
e36e88127d Merge pull request #530 from cytopia/third-party-devilbox-cli
Documentation: devilbox-cli.sh
2019-03-09 11:32:10 +01:00
73cc2d9b1e Refs #527 Add third-party tool info page: devilbox-cli.sh 2019-03-09 11:22:32 +01:00
8840ce67e4 Merge pull request #529 from cytopia/vendor-phpmemcached
Vendor PHPMemcachedAdmin
2019-03-09 11:16:39 +01:00
afb7d3a577 Fix indentation 2019-03-09 11:14:00 +01:00
54d7b0d1a1 Bump version date 2019-03-09 11:10:54 +01:00
962ae92943 Fix #525 Add docs for PHPMemcachedAdmin 2019-03-09 11:10:31 +01:00
f5bba1732a Fix #525 Add PHPMemcachedAdmin 2019-03-09 11:10:27 +01:00
ecf456db1f Merge pull request #528 from cytopia/update-php-image
Fixes #499 and Fixes #496
2019-03-09 02:23:30 +01:00
297a015b72 Fixes #499 and Fixes #496 2019-03-08 21:16:56 +01:00
d20b76aea6 Merge pull request #526 from cytopia/docs-third-party
Fixes #405 add project information to documentation
2019-03-08 15:07:15 +01:00
eb4c68109d Fixes #405 add project information to documentation 2019-03-08 15:04:21 +01:00
50ab236ea9 Merge pull request #524 from cytopia/documentation-contao
Documentation Contao CMS
2019-03-07 17:49:22 +01:00
e81b456ec3 Add follow up steps for framework/cms examples 2019-03-07 17:23:41 +01:00
c27ac1a8e9 Update CHANGELOG 2019-03-07 17:23:36 +01:00
8ab6b24925 Add configurable PSA banner across all doc pages 2019-03-07 17:23:32 +01:00
dab5c1e2ea Enhance example with note about Symlinks on Docker Toolbox 2019-03-07 17:23:28 +01:00
6ce9a94509 Add documentation: setup Contao CMS 2019-03-07 17:23:24 +01:00
5421d45d82 Merge pull request #523 from cytopia/update-php
Use latest 2.7 release of Xdebug
2019-03-07 17:22:58 +01:00
1b5f40278d Use latest 2.7 release of Xdebug 2019-03-07 00:49:11 +01:00
3d805b1191 Merge pull request #522 from cytopia/feature-ngrok
Feature ngrok
2019-03-06 22:05:36 +01:00
83823e0ccf Update versioning files 2019-03-06 14:11:25 +01:00
bc987a5663 \#453 Add Ngrok Documentation 2019-03-06 14:10:33 +01:00
a7133dd6ed #453 Add Ngrok Compose override file 2019-03-06 14:08:51 +01:00
e8fa029de6 Merge pull request #521 from cytopia/docker-nginx
Nginx worker|connection settings via .env
2019-03-05 08:37:06 +01:00
5263cb6a8b Bump version date 2019-03-04 08:53:01 +01:00
719a127205 Update Changelog 2019-03-04 08:52:37 +01:00
e9abde6194 shell.bat does not need to have executable bit set 2019-03-04 08:50:35 +01:00
6c851a5772 Fixes #393 Be able to customize worker_processes and worker_connections 2019-03-04 08:50:04 +01:00
ec1d312c41 Merge pull request #520 from cytopia/nginx-request-entity-limitations
Set client_max_body_size to 0 for Nginx to be in line with Apache
2019-03-04 08:32:03 +01:00
489695268f Add info about HTTPS 2019-03-03 16:31:03 +01:00
48fb8c5909 Fixes #356 Set client_max_body_size to 0 for Nginx to be in line with Apache 2019-03-03 16:12:05 +01:00
31586cb6e1 Merge pull request #518 from cytopia/wkhtmltopdf-with-qt
Switching to wkhtmltopdf with QT patch enabled
2019-03-03 04:40:42 +01:00
f638f98fa3 Fixes #493 Switching to wkhtmltopdf with QT patch enabled 2019-03-02 22:29:04 +01:00
4e787aa8a4 Merge pull request #519 from cytopia/docs-important
Documentation: Add IMPORTANT section
2019-03-02 20:42:16 +01:00
7d371cc66d Documentation: Add IMPORTANT section 2019-03-02 20:40:45 +01:00
78c76f6b7e Merge pull request #517 from cytopia/docs-xdebug
Fixes #381 Rewrite and simplify Xdebug documentation
2019-03-02 18:02:56 +01:00
408687e9ed Fix sphinx error 2019-03-02 18:02:07 +01:00
cd60aa7568 Fixes #381 Rewrite and simplify Xdebug documentation 2019-03-02 18:00:20 +01:00
771b01aec0 Merge pull request #516 from cytopia/docs-toolbox-symlinks
Fixes #479 Documentation: Docker Toolbox on Windows and Symlinks
2019-03-02 15:55:27 +01:00
62b506470c Fixes #479 Documentation: Docker Toolbox on Windows and Symlinks 2019-03-02 14:42:41 +01:00
9375340426 Merge pull request #515 from cytopia/docs-magento2
Documentation: Magento 2 install example
2019-03-02 12:49:28 +01:00
7016f65ae3 Fixes #483 Add note to use Apache 2.4 by default for Magento 2 example 2019-03-02 12:46:24 +01:00
7cb9502c1e Merge pull request #514 from cytopia/backport-from-release-1.0.0
Backport non-breaking changes from Release v1.0.0
2019-03-02 12:05:58 +01:00
200135164b Backport non-breaking changes from Release v1.0.0 2019-03-01 13:59:33 +01:00
b92d9900ac Merge pull request #512 from cytopia/varnish-ssl-offloading
Varnish SSL offloading with HAProxy
2019-02-28 13:51:18 +01:00
d7a0cdb662 Use diagrams from artwork repository 2019-02-28 12:49:45 +01:00
cb6f109b4f Fix redirected link 2019-02-28 12:43:33 +01:00
47c830116a Ensure README is generated idempotently 2019-02-28 12:43:28 +01:00
8496818dec Keep CHANGELOG in sync 2019-02-28 12:43:24 +01:00
7aaa6d3ea6 Provide Architecture overview in README 2019-02-28 12:43:20 +01:00
5343cabcdc Refs #480 Add HAProxy SSL offloading documentation 2019-02-28 12:43:15 +01:00
cdb27c836f Refs #480 Add HAProxy in front of Varnish for SSL offloading 2019-02-28 12:43:11 +01:00
b76a568a8b Merge pull request #513 from cytopia/docs-restart-devilbox
Docs restart Devilbox (docker-compose rm -f)
2019-02-28 12:42:27 +01:00
c32b8462e2 Add architecture diagram 2019-02-28 12:37:47 +01:00
16131d3c87 Fixes #426: Emphasize importance of docker-compose rm 2019-02-28 12:37:30 +01:00
1b1004c87e Merge pull request #510 from cytopia/elk-stack
ELK stack
2019-02-26 21:39:29 +01:00
d10eab8471 Update CHANGELOG 2019-02-23 12:14:15 +01:00
dfc0bdde21 Bump version date 2019-02-23 12:10:55 +01:00
0cb503db49 Reflect container changes in main README 2019-02-23 12:10:43 +01:00
7f58dd9a79 Refs: #360 Add documentation for ELK stack 2019-02-23 12:03:56 +01:00
cb74322d1a Append info about env variables 2019-02-23 12:02:38 +01:00
e15c019eea Consolidate overwrite files 2019-02-23 12:02:13 +01:00
588c537199 Refs: #360 Add ELK stack 2019-02-23 11:59:49 +01:00
fe5c3bb63d Merge pull request #509 from cytopia/varnish-mount
Varnish custom configs
2019-02-17 18:18:02 +01:00
68f49c0be6 Adjust documentation to reflect custom Varnish config mounts 2019-02-17 12:04:05 +01:00
6fb39c0e69 Ensure Varnish can mount custom configurations 2019-02-17 11:53:43 +01:00
325acdf89a Merge pull request #508 from cytopia/features
Feature: Add Varnish to Devilbox stack
2019-02-17 10:29:24 +01:00
5bb4ae5db6 Update Changelog 2019-02-16 21:13:20 +01:00
447678413e Bump version 2019-02-16 21:12:48 +01:00
ae0ced0a67 Add documentation for Varnish 2019-02-16 21:12:34 +01:00
e4a5d09fd9 Provide Varnish docker-compose.override.yml files 2019-02-16 21:11:58 +01:00
84830a86c5 Use latest PHP-FPM images 2019-02-16 20:38:14 +01:00
047be5ac0a Merge pull request #507 from cytopia/ci-tests
Add HTTPS CI tests
2019-02-16 19:03:38 +01:00
57aa1846b9 Add CI tests against HTTPS 2019-02-16 13:27:46 +01:00
384976a780 Backport tests from release branch 2019-02-16 13:27:18 +01:00
cc6de2dfa1 Merge pull request #502 from cytopia/php-8.0
PHP-FPM 8.0
2019-02-10 15:23:25 +01:00
598358e99e Allow to disable certain version for vendor checks 2019-02-10 12:29:42 +01:00
25e94d28cb Add PHP-FPM 8.0 2019-02-09 16:51:40 +01:00
1db72efa5e Merge pull request #495 from cytopia/update-php-version
Update PHP container
2019-02-07 12:42:50 +01:00
a8321eefe5 Merge pull request #494 from mrbig00/patch-1
Fix example command @ customizing vhost template
2019-02-07 08:41:40 +01:00
324e2539c1 Update PHP container 2019-02-06 20:16:03 +01:00
decaa8ed66 Fix example command @ customizing vhost template 2019-02-06 20:29:52 +02:00
ddf1bbb3b5 Merge pull request #491 from cytopia/repository-upgrade
Release preparation
2019-02-05 17:25:43 +01:00
546ad07150 Disable Mongo login for PHP 7.3 due to xdebug issues 2019-02-05 12:46:03 +01:00
ff81e6b897 Use correct hostnames in check instead of 127.0.0.1 2019-02-05 12:45:59 +01:00
d4688be7e2 Update Adminer to latest version 2019-02-05 12:45:54 +01:00
fe343ad2f9 Backport repository files from v1.0.0 release 2019-02-05 12:45:50 +01:00
54eb7be023 Update PHP-FPM 7.3 with latest xdebug module 2019-02-05 12:45:46 +01:00
59a098303b Update PR template to specify goal 2019-02-05 12:45:42 +01:00
d67b8c1ea7 Merge pull request #492 from felixmosh/fix-doc-typo
Align port number
2019-02-03 19:28:33 +01:00
d21f96f211 Align port number 2019-02-03 20:25:35 +02:00
d00ebe7176 Merge pull request #489 from cytopia/phppgadmin-autologin
phpPgAdmin autologin
2019-01-30 18:49:32 +01:00
4ee37cb9a9 Bump version 2019-01-30 15:53:27 +01:00
47ed08d61b Refs #476 Adjust documentation for phpPgAdmin autologin 2019-01-30 15:53:23 +01:00
a1fc1863fb Refs #476 Adjust tests for phpPgAdmin autologin 2019-01-30 15:53:19 +01:00
f20e8205d8 Refs #476 Enable autologin for phpPgAdmin 2019-01-30 15:53:15 +01:00
5c492f3089 Merge pull request #488 from cytopia/file-permissions
Check against correct phpMyAdmin config permissions
2019-01-30 15:52:36 +01:00
1ab9ff778a Refs #342 Regression test: Ensure phpMyAdmin is configured correctly 2019-01-30 13:35:43 +01:00
eef3582b93 Check against correct phpMyAdmin config permissions 2019-01-30 02:07:56 +01:00
cd20dc00b7 Merge pull request #478 from mrbig00/patch-1
Config phpmyadmin 4.8.4 to autologin
2019-01-30 01:08:40 +01:00
a47a497597 Remove pre-login from phpMyAdmin CI test 2019-01-29 18:02:31 +01:00
4324f13714 Add documentation entry for env settings about phpMyAdmin autologin 2019-01-29 15:59:08 +01:00
6caaea6b34 Configure old phpMyAdmin version for autologin 2019-01-29 15:59:04 +01:00
7a75f04952 Make autologin configurable 2019-01-29 15:59:00 +01:00
233c906d57 Change hostname from 127.0.0.1 to mysql 2019-01-29 15:58:56 +01:00
67c3d8bd13 Config phpmyadmin 4.8.4 to autologin 2019-01-29 15:58:51 +01:00
94466a0d1f Merge pull request #487 from cytopia/documentation-docker-compose-override
Documentation docker compose override
2019-01-29 12:56:59 +01:00
728c17b5f5 Bump version 2019-01-29 12:51:15 +01:00
7ac909566f Refs #451 Improve docs about docker-compose.override.yml 2019-01-29 12:50:45 +01:00
4a43c155a7 Merge pull request #470 from cytopia/documentation-blackfire
Blackfire improvements
2019-01-28 14:43:09 +01:00
56a5faaf44 Adjust TL;DR section of blackfire documentation 2019-01-28 11:45:12 +01:00
872ae0d536 Ensure startup scripts are tested correctly 2019-01-28 11:35:59 +01:00
5c951bbfb3 Only configure blackfire cli if binary is present 2019-01-28 11:35:40 +01:00
8ebf735e9d Bump Devilbox version 2019-01-28 02:37:44 +01:00
30156f108e Adjust blackfire documentation 2019-01-28 02:37:40 +01:00
5686e415cc Provide default blackfire php.ini files 2019-01-28 02:37:35 +01:00
a4c05d34e9 Fix autostart script for blackfire to only configure client 2019-01-28 02:37:31 +01:00
e09d6a06b8 Add blackfire client configuration to override.yml-all 2019-01-28 02:37:26 +01:00
43ca5a8a1f Add blackfire client configuration 2019-01-28 02:37:22 +01:00
3cc0448446 Add blackfire-agent startup script (configure and run) 2019-01-28 02:37:18 +01:00
44279ea9c1 Refs #451 Ensure to properly document how to enable blackfire 2019-01-28 02:37:13 +01:00
33600fe1ba Merge pull request #485 from cytopia/editorconfig
Editorconfig
2019-01-28 01:11:14 +01:00
20f3dfa86f Ensure correct executable bit is set 2019-01-26 19:52:44 +01:00
4caf169c9d Ensure current files adhere to .editorconfig 2019-01-26 19:52:40 +01:00
8fa2c56060 Refs #481 Adding editorconfig 2019-01-26 19:52:36 +01:00
93010826ee Merge pull request #484 from cytopia/documentation-links
Fix documentation links
2019-01-26 19:50:29 +01:00
f1d4771aba Merge pull request #477 from ibnuh/patch-1
Fix typo setup-yii.rst
2019-01-26 17:22:16 +01:00
ce2b83f06d Fix documentation links 2019-01-26 17:18:19 +01:00
0460c92775 Fix typo setup-yii.rst 2019-01-18 14:46:42 +07:00
67db5ac40c Merge pull request #474 from cytopia/bugfix-release
Bugfix release
2019-01-17 09:34:51 +01:00
88729db0cc Fixes #472 Ensure to fail on invalid vhost-gen override file 2019-01-16 18:21:22 +01:00
d57446b6dc Fixes #471 Adding zip binary 2019-01-16 18:20:30 +01:00
3400c02b45 Merge pull request #468 from cytopia/php-cs-fixer
Feature Release: Foreign Function Interface (FFI) and PHP-CS-Fixer
2019-01-13 02:20:56 +01:00
765ffb3232 Update to latest PHP-FPM images 2019-01-12 17:41:37 +01:00
8c6c95e32d Bump version 2019-01-12 14:58:30 +01:00
26c90d4bec Use latest PHP-FPM Docker images 2019-01-12 14:58:10 +01:00
0091e59adb Fixes #467 Add tool: PHP CS Fixer 2019-01-11 10:52:59 +01:00
74bd19b241 Merge pull request #457 from cytopia/blackfire
PHP Blackfire
2019-01-09 22:09:05 +01:00
119b2e2a6c Bump version date 2019-01-08 08:58:15 +01:00
c643f81ce5 Fix 2019-01-08 08:57:34 +01:00
d74ff4f01d Merge pull request #464 from cytopia/fix-global-vhost-gen
Use new HTTP container that properly read global vhost-gen config
2019-01-08 08:53:21 +01:00
1c846d4e5b Fixes #463 Use new HTTP container that properly read global vhost-gen config 2019-01-07 19:16:42 +01:00
bd12669b88 Merge pull request #462 from cytopia/http2-support
Use HTTP/2 as default for all SSL connections
2019-01-07 18:59:17 +01:00
eb53315861 Update vhost-gen templates 2019-01-06 13:02:38 +01:00
9fb398a5ee Bump version 2019-01-06 12:58:26 +01:00
d5caba5e11 Fixes #431: Use HTTP/2 as default for all SSL connections 2019-01-06 12:54:34 +01:00
2c0264a436 Merge pull request #461 from ztickm/patch-1
Fixed Typo: color to colon
2019-01-06 01:40:10 +01:00
188b22d65d Fixed Typo: color to colon 2019-01-06 00:09:14 +01:00
f647f16b7b Merge pull request #460 from keithy/patch-1
typo
2019-01-05 17:27:54 +01:00
89cb711f55 typo 2019-01-05 14:20:06 +00:00
e91638552a Merge pull request #458 from cytopia/cytopia-patch-1
Update issue templates
2019-01-04 15:26:54 +01:00
e1867c01dc Update issue templates 2019-01-04 15:23:59 +01:00
930e074e2f Merge pull request #456 from cytopia/community-forum
Fixes #245 Discourse community forums
2019-01-03 18:43:30 +01:00
b6763ad40f Fixes #245 Add Discourse forums 2019-01-03 17:57:35 +01:00
40d9bd1b85 Merge pull request #452 from cytopia/oracle-support
Fixes #394 Native Oracle Database support for PHP
2019-01-02 14:55:22 +01:00
39d1e1eb5a Fixes #394 Native Oracle Database support for PHP 2019-01-01 21:39:56 +01:00
5cc0b548c6 Merge pull request #449 from cytopia/vendors
Reverse Proxy, Autostart and phpPgAdmin
2018-12-31 16:57:47 +01:00
3a3aec4d66 Bump version 2018-12-31 13:41:57 +01:00
83eb20d138 Add autostart and reverse proxy documentation 2018-12-31 13:14:29 +01:00
782a7c05be Simplify Reverse Proxy vhost-gen templates 2018-12-31 10:55:22 +01:00
c93f97ce2e Fix vhost-gen documentation to also reflect changes of rproxy templates 2018-12-29 17:38:15 +01:00
03ead39f2c Remove duplicate newlines 2018-12-29 15:39:41 +01:00
f60af9b8f8 Refs #240 use HTTPD images with reverse proxy capabilities 2018-12-29 15:27:15 +01:00
ccb70befc3 Reflect Reverse proxy capabilities in README 2018-12-29 15:25:41 +01:00
529646520d Normalize vhost-gen configs 2018-12-29 14:23:13 +01:00
b23fef2fa4 Ensure tests really fail in case of errors 2018-12-29 14:22:51 +01:00
0bf985103c Fix vhost-gen templates for reverse proxy settings 2018-12-29 13:55:53 +01:00
cf5fb86e4b Update vhost-gen templates 2018-12-29 13:13:01 +01:00
4c45a7e33d Add global autostart example 2018-12-29 13:12:38 +01:00
1dfa98446b Rewrite tests to also accompany for rproxy tests 2018-12-29 13:12:06 +01:00
ccd3f1dbc2 Enable new autostart behaviour: per version and for all 2018-12-29 00:19:54 +01:00
f2b0773fb5 Clean-up docker-compose.yml 2018-12-28 23:56:14 +01:00
a1b1d9ad93 Provide phpPgAdmin default configuration 2018-12-28 23:49:25 +01:00
3e4517ec42 Fix phppgadmin test on failure 2018-12-28 23:33:54 +01:00
1ffaf4ce92 Bump version date 2018-12-28 23:08:09 +01:00
15e72edb5f Use PHP-FPM 0.64 images 2018-12-28 22:49:51 +01:00
a96da64830 Distinguish between base, mods and available php extensions 2018-12-28 22:47:35 +01:00
de44f23594 Add phpPgAdmin to README 2018-12-28 22:45:54 +01:00
2e580b29f0 Fix retrieval of available PHP extensions 2018-12-28 22:45:30 +01:00
46141b7e50 Update readthedocs for phpPgAdmin 2018-12-28 22:44:50 +01:00
5c95242111 Add vendor: phpPgAdmin 2018-12-28 22:38:09 +01:00
93c16d4e03 Merge pull request #446 from cytopia/custom-startup-scripts
Custom startup scripts
2018-12-27 17:21:21 +01:00
4e44082cd8 Import GPG key into rpm before installing software to ensure it is valid 2018-12-27 14:28:49 +01:00
79b197822a Ensure oracle oci8/pdo_oci work on every version 2018-12-27 14:14:01 +01:00
fad12d120d Tie PHP module check against currently used php-fpm tag 2018-12-27 13:51:09 +01:00
7fabead92d Auto accept EULA for CI tests 2018-12-27 13:46:31 +01:00
cb7ec86765 Test startup files 2018-12-27 13:18:42 +01:00
ddbe0f9bb6 Test against available php modules 2018-12-27 13:10:51 +01:00
b37afe3268 Use latest PHP images without env var name collisions 2018-12-26 17:36:47 +01:00
dbd69c8d59 Refs #394 - Add startup script examples for Oracle instaclient 2018-12-26 17:36:09 +01:00
d930c08a45 Fix requirements to build documentation 2018-12-26 17:31:23 +01:00
09c564c68d Add documentation for custom startup scripts 2018-12-26 17:31:09 +01:00
30ea9ff2b5 Fix undefined variable in intranet vhost_gen overview 2018-12-26 15:31:15 +01:00
42602d2ce3 Bump version date 2018-12-26 12:15:00 +01:00
3359bd3f9a Pull docker images until success to circumvent short network outages 2018-12-26 11:55:01 +01:00
0115ee3b77 Allow for custom startup scripts 2018-12-25 16:40:19 +01:00
aa574e9205 Adjust ignored files 2018-12-25 16:39:48 +01:00
8f38cbd736 Add examples for how to install Ms ODBC after accepting the license 2018-12-25 16:39:34 +01:00
3260e68c90 Merge pull request #445 from cytopia/update-php
Refs #439 Adding sqlsrv and pdo_sqlsrv for PHP 7.0, 7.1, 7.2 and 7.3
2018-12-23 17:19:31 +01:00
6e238cc095 Refs #439 Adding sqlsrv and pdo_sqlsrv for PHP 7.0, 7.1, 7.2 and 7.3 2018-12-23 12:19:38 +01:00
3ebeebef10 Merge pull request #444 from cytopia/update-php
Update to latest PHP container
2018-12-23 01:22:30 +01:00
8fd60fb9a9 Update to latest PHP container 2018-12-22 22:38:32 +01:00
f7bfc72cd2 Merge pull request #443 from cytopia/use-alpine-images
Use alpine images
2018-12-21 17:43:05 +01:00
97a62d3efe Remove Redis 2.8-alpine as it does not exist 2018-12-21 11:51:20 +01:00
80b7682f89 Speed up Docker pull tests and be easy on network usage 2018-12-20 23:26:15 +01:00
d5d43d0c71 Fix drush check for intranet homepage 2018-12-20 20:05:29 +01:00
d1e5c6d360 Add commented Alpine versions and adjust warning note 2018-12-20 20:04:50 +01:00
3bbefdc845 Remove old MongoDB image versions that segfault after startup 2018-12-20 17:41:15 +01:00
16bbaf4b3a Do not use Alpine image by default, but document how to enable them 2018-12-20 13:50:20 +01:00
8d005f5a70 Bump version date 2018-12-20 11:33:23 +01:00
2e86bbafd0 Ensure all provided images are properly tested via TravisCI 2018-12-20 11:32:43 +01:00
6a4083a7a3 Fixes #429 Adding smaller Alpine images where possible 2018-12-20 11:32:14 +01:00
3b73b1c5e5 Merge pull request #442 from cytopia/devilbox-ui
Devilbox Web UI: Vhost overview
2018-12-19 17:56:09 +01:00
4c39ae9edf Add integration tests for Devilbox vhost web ui 2018-12-19 14:16:27 +01:00
e8c38550c9 Extend Devilbox web ui with vhost configs 2018-12-19 14:16:04 +01:00
fb5bbcd1e1 Merge pull request #441 from cytopia/update-vendors
Update intranet vendors
2018-12-18 21:54:22 +01:00
35ff034786 Ensure to exclude breaking tests 2018-12-18 20:29:51 +01:00
09ac5f3f85 Fix check against PHP version 2018-12-18 14:47:09 +01:00
d8794950c0 Disable phpRedmin CI tests for PHP 5.3 and PHP 5.4 2018-12-18 14:40:41 +01:00
112e3d2c33 Adjust phpRedmin configuration 2018-12-18 14:30:50 +01:00
c9d3dab042 Attach latest HTTPD images 2018-12-18 12:47:35 +01:00
586cd2a882 Ensure PHP Xdebug does not autostart 2018-12-18 11:51:12 +01:00
d9272d5c52 Attach latest PHP-FPM images 2018-12-18 11:13:04 +01:00
c1d8516d84 Bump Devilbox version date 2018-12-17 11:59:16 +01:00
bfd0b22676 Upgrade PHP container versions 2018-12-17 11:58:52 +01:00
a9d56daaa0 Exclude experimental PHP versions from Xdebug check 2018-12-17 11:57:28 +01:00
e925c47b78 Ensure to test subdirectories of PHPRedmin 2018-12-17 11:01:29 +01:00
4588948d0c Test against PHP Xdebug 2018-12-16 16:10:39 +01:00
008cb7c023 Fix phpMyAdmin login check 2018-12-16 15:44:42 +01:00
1d075f4b3b Add login CI tests for phpMyAdmin 2018-12-16 15:31:22 +01:00
2b9c98bbc7 Update phpMyAdmin 2018-12-16 15:31:03 +01:00
689a8b9f12 Fix check for selecting Adminer/phpMyAdmin version 2018-12-16 02:16:50 +01:00
590855fe75 Supress stderr when gathering binary versions to prevent log spamming 2018-12-16 00:39:22 +01:00
178a81c24b Check against PHPRedmin 2018-12-16 00:34:59 +01:00
a459597759 Ensure Adminer and phpMyAdmin work with old PHP versions 2018-12-16 00:29:50 +01:00
60b2d99c09 Pipe curl output into double tac to prevent broken pipe 2018-12-15 22:58:29 +01:00
a652b0d8c5 Create CI tests for Adminer and phpMyAdmin 2018-12-15 22:22:21 +01:00
ae9330be96 Update Adminer from 4.6.2 to 4.7.0 2018-12-15 22:22:00 +01:00
9efc68b62d Merge pull request #435 from cytopia/redis-ui
Bugfixes: PHP-xdebug, Redis UI and Memcached UI
2018-12-15 20:51:05 +01:00
a237ce85d0 Simplify travis configuration 2018-12-15 17:58:17 +01:00
eff72f41a9 Update version 2018-12-15 17:12:56 +01:00
60774c0532 Ensure nc command exits properly when looking up Memcached data 2018-12-15 17:04:26 +01:00
788cea98a1 Do not load MongoDB driver if no connection exists 2018-12-15 17:03:45 +01:00
42630ab62e Fix #434 Add Xdebug to PHP 7.3 2018-12-15 14:05:54 +01:00
01cdfca7fb Integration tests for Redis and Memcached UI 2018-12-15 14:05:10 +01:00
c143eac015 Default keys for Redis and Memcached 2018-12-15 14:05:05 +01:00
8e038d403c Allow to delete keys in Redis via UI 2018-12-15 14:05:00 +01:00
e916c5100d Merge pull request #436 from cytopia/php-versions
Use latest PHP-FPM images
2018-12-10 20:04:04 +01:00
de9c9b6eb1 Use latest PHP-FPM images 2018-12-10 14:42:45 +01:00
bb42602cb3 Merge pull request #437 from cytopia/documentation-links
Fix Shopware documentation link
2018-12-10 14:41:36 +01:00
ed862b9666 Fix Shopware documentation link 2018-12-10 14:40:56 +01:00
d4e5aae7bf Merge pull request #430 from cytopia/travis-checks
Ensure to test against different Docker and Docker Compose versions
2018-12-10 13:51:08 +01:00
56672eec23 Replace test scripts with Makefile 2018-12-10 00:43:42 +01:00
330d047495 Ensure to run different Docker and Docker Compose versions 2018-12-08 14:06:22 +01:00
ea9631790e Merge pull request #428 from cytopia/docker-images
Fixes #423 once and for all: Keep Docker images up-to-date
2018-11-18 12:58:13 +01:00
28ed6b2a24 Fixes #423 once and for all: Keep Docker images up-to-date 2018-11-17 17:46:33 +01:00
e7d4800ad7 Merge pull request #427 from cytopia/fix-mongo
Fix #425 Ensure MongoDB data directory is ignored by git
2018-11-17 15:58:20 +01:00
032aefadb3 Fix #425 Ensure MongoDB data directory is ignored by git 2018-11-17 13:39:58 +01:00
208cd03a11 Merge pull request #422 from cytopia/specify-magento
Documentation: Specify Magento version
2018-11-12 09:20:15 +01:00
212ac6764a Documentation: Use Magento 2 instead of Magento where applicable 2018-11-12 09:04:07 +01:00
93a7cfeb8c Specify Magento 2
Magento 2 and 1 are both pretty prevalent at the moment, I feel it's helpful to specify in the sidebar that this is setting up **magento 2**
2018-11-11 16:44:45 +01:00
b45284bc0f Merge pull request #421 from cytopia/update-php-container
Minor fixes
2018-11-11 16:43:58 +01:00
f91ef8d9cc Refs #250: Documentation - Fix php.ini comments from # to ; 2018-11-11 13:32:50 +01:00
b7862cd9bf Update PHP container 2018-11-10 21:26:17 +01:00
ef5b35378b Merge pull request #420 from cytopia/docs-fix-links
Documentation: Fix redirect links
2018-11-10 13:00:53 +01:00
d9af495862 Documentation: Fix redirect links 2018-11-09 09:05:33 +01:00
ce3d9655a1 Merge pull request #419 from AGPDev/master
Visual improvment in vhosts list
2018-11-08 18:59:40 +01:00
d3b15cd40a Fix wrong HTML table head tag 2018-11-08 14:24:39 -02:00
c2c02ff351 Ordening vhost list asc 2018-11-08 14:23:39 -02:00
a49633f377 Merge pull request #417 from TheGlenn88/patch-1
Phalcon routes fix
2018-11-08 16:54:46 +01:00
44132c9c52 Update setup-phalcon.rst 2018-11-08 14:48:30 +00:00
8f14054606 Update setup-phalcon.rst 2018-11-08 08:54:12 +00:00
0f57b9f623 Phalcon routes fix 2018-11-08 00:12:16 +00:00
cf328ef126 Merge pull request #415 from cytopia/update-php-container
Use latest version of PHP container
2018-11-06 12:35:37 +01:00
8dd678a118 Use latest version of PHP container 2018-11-06 11:20:51 +01:00
564c6a97f7 Merge pull request #412 from cytopia/update-php-images
Use latest PHP images
2018-11-04 16:39:59 +01:00
71b31218b0 Use latest PHP images 2018-11-04 14:02:26 +01:00
4b8d60feff Merge pull request #410 from cytopia/php-7-4
Adding PHP-FPM 7.4-dev (Seven Four)
2018-11-03 15:23:43 +01:00
a3dcc12cde Allow linkcheck to ignore SSL certificate issues 2018-11-03 12:33:06 +01:00
7f0f312a37 Bump PHP version which supports Redis on PHP 7.4 2018-11-03 12:32:40 +01:00
2e9f5e48c4 Adding PHP-FPM 7.4 2018-11-02 22:55:15 +01:00
528eb45738 Merge pull request #408 from cytopia/update-docker-php-fpm-images
Fixes #367 Latest PHP-FPM images
2018-11-02 15:19:26 +01:00
708471a640 Fixes #367 Latest PHP-FPM images 2018-11-02 12:13:27 +01:00
c3af49f401 Merge pull request #407 from cytopia/documentation-performance-osx
Refs #105 document how to mitigate OSX performance issues
2018-11-01 10:52:56 +01:00
9289fa17e7 Refs #105 document how to mitigate OSX performance issues 2018-11-01 10:50:10 +01:00
0188970367 Merge pull request #406 from cytopia/intranet-drush-versions
#401 Fix display of drush versions
2018-11-01 10:22:08 +01:00
7769e34794 #401 Fix display of drush versions 2018-11-01 10:19:43 +01:00
14cd1f0838 Merge pull request #404 from sonyarianto/patch-2
Another typo fix
2018-10-27 11:18:40 +02:00
d0d63461e2 Another typo fix 2018-10-27 11:02:13 +07:00
e70cfb1fcc Merge pull request #402 from cytopia/docs-readme
Update community section
2018-10-26 09:38:50 +02:00
d6a843bd71 Update community section 2018-10-26 09:27:06 +02:00
a13d7a26c4 Merge pull request #400 from sonyarianto/master
Fix brand typo, Wordpress to WordPress
2018-10-24 20:38:57 +02:00
bf8c087622 Fix minor typo 2018-10-24 23:11:13 +07:00
1525e62429 Merge branch 'master' into master 2018-10-24 23:05:39 +07:00
49bdceaccf Fix brand typo, Wordpress to WordPress 2018-10-24 23:04:51 +07:00
4812061c12 Merge pull request #399 from sonyarianto/patch-1
Fix typo
2018-10-24 04:18:07 +02:00
31b1423b7a Fix typo 2018-10-23 10:30:49 +07:00
751820a178 Merge pull request #397 from cytopia/git-directories
Fix #396: typo in gitignore
2018-10-10 09:27:14 +02:00
d2aa3c5f77 Fix #396: typo in gitignore 2018-10-09 09:50:34 +02:00
77d5bdc108 Merge pull request #395 from polo2ro/patch-1
Update customize-specific-virtual-host.rst
2018-10-05 16:32:42 +02:00
fe30f536e2 Update customize-specific-virtual-host.rst 2018-10-05 10:04:04 +02:00
f561c8c951 Merge pull request #392 from cytopia/update-php-container
Add tool: wkhtmltopdf
2018-10-02 09:27:45 +02:00
5e5144c57f Add tool: wkhtmltopdf 2018-10-01 11:13:32 +02:00
ad66bdc9d9 Merge pull request #391 from cytopia/update-php-container
Update PHP container with different drush binaries
2018-10-01 11:11:02 +02:00
0e917deb7c Fixes #384 Update PHP container with different drush binaries 2018-09-30 12:47:40 +02:00
753a53334f Merge pull request #390 from cytopia/github-templates
Update issue templates
2018-09-30 10:19:54 +02:00
7bc8b6ea92 Update issue templates 2018-09-30 10:18:28 +02:00
a8eaabda4f Merge pull request #387 from cytopia/rdkafka
Fixes #385 Adding rdkafka-enabled PHP container
2018-09-28 11:05:02 +02:00
4de394ee88 Fixes #385 Adding rdkafka-enabled PHP container 2018-09-27 09:48:14 +02:00
35a5a38a9a Merge pull request #379 from cytopia/update-php-images
Refs #378: Add tool: Deployer
2018-09-14 14:33:09 +02:00
dd4eff2efd Refs #378: Add tool: Deployer 2018-09-14 08:58:16 +02:00
c84235c620 Merge pull request #377 from cytopia/update-php-docker-images
Fix #376 Adding graphviz-capable Docker images
2018-09-12 18:06:49 +02:00
3b0b12ac6c Fix #376 Adding graphviz-capable Docker images 2018-09-12 08:46:16 +02:00
a81decf6df Merge pull request #375 from Harmageddon/patch-1
Switched phpMyAdmin and phpRedMin
2018-09-11 21:02:54 +02:00
d0064394ad Switched phpMyAdmin and phpRedMin
The two labels got confused.
2018-09-08 20:17:44 +02:00
f10e51dd6d Merge pull request #372 from cytopia/documentation-vhost-gen
Fix #362 - Document how to add multiple server names for Apache 2.2 and Apache 2.4
2018-09-05 14:39:49 +02:00
359eb5990d Fix #362 - Document how to add multiple server names for Apache 2.2 and Apache 2.4 2018-09-05 08:51:08 +02:00
0b0462f8d6 Merge pull request #370 from cytopia/update-php-container
Update PHP container
2018-08-31 08:31:44 +02:00
7fc5bd4a70 Update PHP container 2018-08-30 08:24:20 +02:00
60f8b2c2e0 Merge pull request #368 from cytopia/latest-php-version
Fix #367: Usage latest PHP version
2018-08-29 22:20:20 +02:00
e8553504c3 Fix #367: Usage latest PHP version 2018-08-29 08:33:45 +02:00
ba17ae3811 Merge pull request #364 from cytopia/default-php-modules
Fix #361: Disable swoole by default
2018-08-29 08:29:10 +02:00
2f2ad5bbe0 Merge pull request #366 from texeltexel2009/patch-1
Fixed small links mixup
2018-08-29 08:27:12 +02:00
c5b238b7f7 Fixed small links mixup
Phpmyadmin and Phpredmin links were in the incorrect place. Just switched places.
2018-08-27 17:03:26 +02:00
0a2ff37fa1 Fix #361: Disable swoole by default 2018-08-24 09:29:42 +02:00
8913fd4536 Merge pull request #358 from cytopia/docker-blackfire
Adding new container: Blackfire
2018-08-19 12:39:08 +02:00
db2bdbca4d Fix table width 2018-08-19 12:32:53 +02:00
77eb96f65e Adding new container: Blackfire 2018-08-19 12:27:42 +02:00
085b96cae7 Merge pull request #357 from cytopia/docker-solr
Adding new container: Solr
2018-08-18 15:10:07 +02:00
5291c97db7 Adjust pre-configured container overview 2018-08-18 14:16:01 +02:00
98552275d0 Adding available container to README 2018-08-18 14:09:20 +02:00
4cd1f2e284 Bump version date 2018-08-18 13:59:02 +02:00
1defa162a8 Fix RabbitMQ variable case in documentation 2018-08-18 13:58:33 +02:00
f25f57dc37 Add links to Container versions 2018-08-18 13:57:59 +02:00
a4c1a1b72c Adding new container: Solr 2018-08-18 13:51:35 +02:00
32fe1ffb5f Merge pull request #354 from cytopia/enable-custom-docker-container
RabbitMQ
2018-08-15 20:53:16 +02:00
1906b6baad Update Devilbox release date 2018-08-15 20:23:54 +02:00
00d5d95221 Fix rst syntax error in headline 2018-08-15 20:23:37 +02:00
9170486cbf Documentation: enable all additional container 2018-08-15 20:20:52 +02:00
0c7a9234bf Fix #57: Add RabbitMQ 2018-08-15 19:54:20 +02:00
994df7d6da MailHog fine-tuning 2018-08-15 19:53:06 +02:00
c77fd90472 Merge pull request #352 from cytopia/release-0.15
Devilbox Release v0.15
2018-08-13 20:36:27 +02:00
acac4f0459 Prepare Devilbox Release v0.15 2018-08-13 01:15:45 +02:00
b9a4ee211d Merge pull request #351 from cytopia/meta
Devilbox intranet, docs and fixes
2018-08-12 18:43:33 +02:00
cf3764cd1d TL;DR Copy/paste instructions 2018-08-12 13:49:00 +02:00
eee6612b0b Make MailHog port configurable 2018-08-12 13:30:05 +02:00
ad69497ce4 Fix #202 Document MailHog integration 2018-08-12 13:20:17 +02:00
94f0b984dd Fix #323 add sane default configurations for the webservers 2018-08-12 12:21:09 +02:00
ff9d6ec972 Preview: Redis 5 2018-08-12 11:54:02 +02:00
cceefb569c Linkcheck: increase retries 2018-08-12 11:51:08 +02:00
8b177c4b05 Note about SSL certificates 2018-08-12 11:46:01 +02:00
0ee032131b Link images 2018-08-12 11:43:00 +02:00
d2b26f5e0f Adjust image size 2018-08-12 11:42:50 +02:00
f2581f0438 Bump version 2018-08-12 11:22:16 +02:00
8cb76c0966 Add documentation for phpRedMin 2018-08-12 11:21:31 +02:00
141b7bf72d Integrate PHPRedMin into Devilbox intranet 2018-08-12 10:52:13 +02:00
ed01a55960 Add PHPRedMin 2018-08-12 10:51:32 +02:00
8e14009d3d Show Redis keys grouped by DB 2018-08-12 10:29:59 +02:00
ed52e7e3d8 Test update script via Travis 2018-08-12 01:21:37 +02:00
bb201d86b1 Update Docker update script 2018-08-12 01:21:12 +02:00
58da41ab85 Merge pull request #350 from cytopia/redis-password
Redis startup options
2018-08-12 00:07:27 +02:00
8df3ed5d8f Fix linkcheck 2018-08-11 23:24:11 +02:00
b0f43a2077 Documentation: Redis startup parameter 2018-08-11 22:42:19 +02:00
32592b03dc Replace Redis password option with Redis startup options to make it more dynamic 2018-08-11 13:50:21 +02:00
d4deff1340 Merge pull request #303 from longelas/redis-custom-pass
Redis-custom-pass
2018-08-11 11:52:39 +02:00
2254ec6c49 Merge pull request #138 from cytopia/DVL-013-fix-dns
(Feedback required) DVL-013 Fix Auto-DNS for non bridged Docker networks
2018-08-11 11:39:46 +02:00
fe3306885c Forward https port 2018-08-11 11:33:17 +02:00
4d9ba6f971 DVL-013 Fix Auto-DNS for non bridged Docker networks 2018-08-11 11:33:14 +02:00
ebdd729212 Merge pull request #297 from cytopia/mount-options
Mount options: Allow SE Linux machines
2018-08-11 11:29:43 +02:00
dead8eac3d Fixes #255 - Document SELinux labels for mount options 2018-08-11 11:14:34 +02:00
7ec9a8df8f Variablize mount options 2018-08-10 09:26:14 +02:00
271230bb62 Merge pull request #349 from kusl/mount-options
Bring Mount options to par with master
2018-08-10 08:54:34 +02:00
a351c7d2d8 add z to /var/mail in docker compose
Signed-off-by: Kushal Hada <kushaldeveloper@gmail.com>
2018-08-09 22:12:43 -04:00
c036270510 Merge branch 'master' of github.com:cytopia/devilbox into mount-options 2018-08-09 20:45:07 -04:00
75836f6afc Merge pull request #348 from cytopia/linkcheck
Fix broken link in docs
2018-08-09 23:11:54 +02:00
8c2362e719 Merge pull request #347 from cytopia/phpmyadmin-settings
Fix #342 phpMyAdmin config permission error
2018-08-09 23:11:12 +02:00
cb992d08a7 Fix broken link in docs 2018-08-09 23:09:28 +02:00
0e25ca5584 Fix #342 phpMyAdmin config permission error 2018-08-09 23:01:33 +02:00
54aa508b11 Merge pull request #346 from cytopia/documentation-craftcms
Fixes #341 - Documentation: Install CraftCMS
2018-08-08 12:34:40 +02:00
245b6e6135 Merge pull request #345 from cytopia/rsync
Fixes #343: Use PHP images with rsync support
2018-08-08 12:29:00 +02:00
8b2f39972f Fixes #341 - Documentation: Install CraftCMS 2018-08-08 09:31:36 +02:00
7b1af0a947 Fixes #343: Use PHP images with rsync support 2018-08-08 08:41:23 +02:00
e91d5eac4f Merge pull request #340 from cytopia/global-vhost-gen-templates
Fix #144 Be able to use global vhost-gen templates
2018-08-06 22:23:34 +02:00
abc3cbc1a2 Unifiy README for Linux, MacOS and Windows 2018-08-06 21:56:59 +02:00
35546e7fa1 Documentation for vhost-gen templates 2018-08-06 21:42:03 +02:00
a1c6510131 Fix table 2018-08-06 20:34:58 +02:00
eb632e27cc Update install instructions 2018-08-06 08:39:15 +02:00
de61ba4a65 Fix #144 Be able to use global vhost-gen templates 2018-08-05 19:24:42 +02:00
fad7571875 Merge pull request #339 from cytopia/php-72-depreceated
Fix PHP 7.2 deprecated function: create_function()
2018-08-05 17:00:49 +02:00
9a9cb55917 Fix PHP 7.2 deprecated function: create_function() 2018-08-05 16:55:26 +02:00
d17e9bf6fe Merge pull request #333 from cytopia/ensure-hostnames-are-fix
ref #331 - Ensure hostnames are fixed
2018-08-05 05:29:11 +02:00
99765bebf0 ref #331 - Ensure hostnames are fixed 2018-08-05 05:20:51 +02:00
9a4538bb37 Merge pull request #338 from cytopia/default-example-configurations
Feature Release: Performance, Timeouts and PHP 5.2
2018-08-05 05:17:22 +02:00
c093aff25c Adding mail dir 2018-08-05 05:13:45 +02:00
c0e220b1bd Make timeout from httpd to php-fpm configurable 2018-08-05 03:04:03 +02:00
e28d56b053 Move sentence to correct headline 2018-08-05 02:43:22 +02:00
7089917126 Make mails survive reboot 2018-08-05 02:41:42 +02:00
0e61de538e Documentation: extend Magento setup instructions 2018-08-04 22:09:42 +02:00
ca33060d25 Use new PHP-FPM images 2018-08-04 22:09:42 +02:00
75765c2063 Fix default listen.backlog 2018-08-04 22:09:41 +02:00
f9db50f03a Warn about problematic TLDs 2018-08-04 22:09:41 +02:00
4ecee3f677 Add Docker logo 2018-08-04 22:09:40 +02:00
24851eb58d Apply new vhost-gen templates 2018-08-04 22:09:40 +02:00
a0982e9bb6 Link documentation and fix minor typos 2018-08-04 22:09:39 +02:00
10b99953f1 Add quickstart instructions for Windows 2018-08-04 22:09:38 +02:00
d50f9c5c24 Documentation: do not use official domains for TLD_SUFFIX 2018-08-04 22:09:38 +02:00
306107d1c6 Documentation about new php default configuration 2018-08-04 22:09:37 +02:00
7d0e0a8fa6 Documentation about PHP 5.2 2018-08-04 22:09:36 +02:00
f1a350c5b3 Add documentation links 2018-08-04 22:09:36 +02:00
66708e2b76 Fix framework links 2018-08-04 22:09:35 +02:00
9e0f65b147 Add PHP 5.2 information 2018-08-04 22:09:35 +02:00
42daba8ba6 Add documentation links 2018-08-04 22:09:34 +02:00
3c7fea1e0f Adding PHP 5.2 compatibility mode 2018-08-04 22:09:33 +02:00
1589dc96fe Fixes #234 and fixes #311 performance issues and 504 Gateway timeouts 2018-08-04 22:09:33 +02:00
1502a7e22b Adjust documentation to newly create Xdebug default configuration 2018-08-04 22:09:32 +02:00
eb0f119f7a Adjust gitignore for PHP 5.2, 5.3 and 7.3 2018-08-04 22:09:20 +02:00
ff7fa9d9ab Generalize default configs for PHP-FPM 2018-08-04 22:09:16 +02:00
b0eeb9b836 Generalize php.ini default configuration 2018-08-04 22:09:12 +02:00
c34416690c Merge pull request #336 from cytopia/github-templates
Update Github issue/pr templates
2018-08-03 10:37:08 +02:00
e49f508b04 Update Github issue/pr templates 2018-08-03 10:33:35 +02:00
0591e44775 Merge pull request #334 from cytopia/documentation-install-magento
Documentation: Install Magento
2018-08-01 00:29:01 +02:00
407a636913 Documentation: Install Magento 2018-08-01 00:12:26 +02:00
bc300ae594 Merge pull request #332 from cytopia/documentation-presta-shop
Documentation presta shop
2018-07-31 21:29:13 +02:00
c789261917 Backport tools to README 2018-07-31 21:27:12 +02:00
0d5eb38bc7 Documentation: Install PrestaShop 2018-07-31 20:21:56 +02:00
8b30fe9507 Merge pull request #330 from cytopia/documentation-wordpress-install
Improve Wordpress installation example
2018-07-31 19:51:24 +02:00
ecfbfe411d Merge pull request #329 from cytopia/documentation-subdomains
ref #324 How to properly add subdomains for the same project
2018-07-31 19:50:35 +02:00
2f4241a865 Improve Wordpress installation example 2018-07-31 19:49:28 +02:00
ab33b268fd ref #324 How to properly add subdomains for the same project 2018-07-31 19:21:27 +02:00
e0ff50089d Merge pull request #328 from cytopia/docs-examples-https
Documentation: more detailed examples
2018-07-30 09:41:54 +02:00
cbd2e62539 Documentation: more detailed examples 2018-07-30 09:32:40 +02:00
fa238275ac Merge pull request #327 from cytopia/fix-email-xss
Fix #326 XSS vulnerability in email display
2018-07-28 09:23:54 +02:00
fb376fe3fa Fix #326 XSS vulnerability in email display 2018-07-28 09:21:43 +02:00
896c2bc0c9 Merge pull request #325 from cytopia/update-available-tools
Update available tools
2018-07-27 19:55:07 +02:00
442a8b1696 Update available tools 2018-07-27 19:42:07 +02:00
d0f138a105 Merge pull request #322 from cytopia/fix-readme
Restore README images
2018-07-27 00:42:01 +02:00
f155123aa4 Restore README images 2018-07-27 00:41:31 +02:00
120bf377d8 Merge pull request #298 from cytopia/restructure-documentation
WIP: Restructuring of documentation
2018-07-26 14:04:28 +02:00
ee45e5e3a6 Fix broken link 2018-07-26 09:50:11 +02:00
dcbff8c44a Generalize links 2018-07-26 09:39:03 +02:00
ddc23aafd8 Fix default file extensions for linkcheck 2018-07-26 09:39:02 +02:00
f7ce65ab94 More sophisticated linkcheck 2018-07-26 09:39:02 +02:00
6ae32fe294 Fix #288 by documenting some edge cases 2018-07-26 09:39:01 +02:00
88ab56c617 Harden linkcheck 2018-07-26 09:39:00 +02:00
56538c10d8 Clean-up unused files 2018-07-26 09:39:00 +02:00
0514c38e54 Validate raw links 2018-07-26 09:38:59 +02:00
ed36d8b709 Change ext link icon from svg to png 2018-07-26 09:38:58 +02:00
2a312b4802 Replace url of static assets 2018-07-26 09:38:58 +02:00
a419efe9c4 External links 2018-07-26 09:38:57 +02:00
74f71a9f59 #244 Connect container to Devilbox network 2018-07-26 09:38:56 +02:00
775180af8b Move links into separate file 2018-07-26 09:38:56 +02:00
ce56d52dd1 #250 PHP Xdebug documentation 2018-07-26 09:38:55 +02:00
b48a7a393f Documentation: Xdebug on MacOS has several ways 2018-07-26 09:38:54 +02:00
e9094fe286 Documentation: Xdebug for Atom 2018-07-26 09:38:54 +02:00
75caa9baa6 Documentation: Add Xdebug section header 2018-07-26 09:38:53 +02:00
0145b26cda Documentation: Update FAQ 2018-07-26 09:38:52 +02:00
091bd57520 Documentation: Fix broken links 2018-07-26 09:38:52 +02:00
586fbd7a93 Documentation: External databases 2018-07-26 09:38:51 +02:00
1f343ce404 Documentation: SSH and SSH tunnelling 2018-07-26 09:38:50 +02:00
dea471b766 Use included links 2018-07-26 09:38:49 +02:00
1c4aa9f1b0 SSH into docker toolbox 2018-07-26 09:38:49 +02:00
cfc80f6ab2 Remove WIP files 2018-07-26 09:38:48 +02:00
954a37211c Documentation: replace external links 2018-07-26 09:38:47 +02:00
bca4cf6a75 Documentation: replace external links 2018-07-26 09:38:47 +02:00
3655988315 Reorganize links 2018-07-26 09:38:46 +02:00
b9c52925f9 Use absolute paths 2018-07-26 09:38:45 +02:00
04e9854470 Restructuring images 2018-07-26 09:38:45 +02:00
04250f2fc3 Shared Devilbox server in LAN 2018-07-26 09:38:44 +02:00
1725de8c48 Add documentation version 2018-07-26 09:38:43 +02:00
5d6a8914d6 Add documentation to connect to external hosts, services or container 2018-07-26 09:38:42 +02:00
b8a571065d Rename custom CNAME creation 2018-07-26 09:38:42 +02:00
bd7c5bd983 #300 Shopware installation guide 2018-07-26 09:38:41 +02:00
88132a0b59 Add more documentation 2018-07-26 09:38:40 +02:00
e56fb56f7c Adjust menu CSS 2018-07-26 09:38:40 +02:00
cd8359332d Add more external links 2018-07-26 09:38:39 +02:00
cfd02321cc Extending support section 2018-07-26 09:38:38 +02:00
1228f5d97a Add example to setup Typo3 2018-07-26 09:38:38 +02:00
af80d6a790 Capitalize headline 2018-07-26 09:38:37 +02:00
ca22a892b1 Move section below correct headline 2018-07-26 09:38:36 +02:00
3c0062b273 Fix external image url 2018-07-26 09:38:36 +02:00
acab8b346e Documentation restructuring 2018-07-26 09:38:35 +02:00
0121371048 Fix external links 2018-07-26 09:38:33 +02:00
2662566677 Merge pull request #319 from cytopia/fix-httpd-silent-mode
Fix #318 vhost creation in non-debug mode
2018-07-25 23:10:02 +02:00
900c7ff4ed Fix #318 vhost creation in non-debug mode 2018-07-25 23:00:42 +02:00
109413cfa8 Merge pull request #309 from cytopia/fix-win-autostart
Fix #242 - Prevent auto-starts on Windows
2018-07-17 08:47:21 +02:00
eafcc2dffc Revert bind autostart 2018-07-16 08:51:11 +02:00
c2dae8ebc2 Fix #242 - Prevent auto-starts on Windows 2018-07-12 22:58:41 +02:00
6f0ca30ad9 Merge pull request #308 from cytopia/github-issue-template
Fix bug report issue type
2018-07-08 12:46:14 +02:00
f5f20cfae9 Fix bug report issue type 2018-07-08 12:45:36 +02:00
c8fb0116df Merge pull request #306 from cytopia/github-issue-template
Iconize issue categories
2018-07-06 17:14:09 +02:00
3b95dcfb48 Split issues into more categories 2018-07-06 17:13:44 +02:00
3b7f9a313d Iconize issue categories 2018-07-06 17:05:40 +02:00
343dc170bb Merge pull request #305 from cytopia/github-issue-template
New issue templates
2018-07-06 16:22:54 +02:00
b061f1c692 New issue templates 2018-07-06 16:22:01 +02:00
47b3491f3a Redis-custom-pass 2018-07-05 23:50:24 +02:00
51298f0662 Merge pull request #289 from kusl/master
add z to everything
2018-06-29 08:57:03 +02:00
0a2fe975b7 Merge branch 'master' into master 2018-06-28 11:29:19 -04:00
3ee0649275 Merge pull request #296 from science695/root-ca-doc
Documentation: Adding in guide link on putting the SSL Root CA into your OS' security keychain
2018-06-27 08:58:25 +02:00
2ee7b6c95e Adding in documentation guide on putting the SSL Root CA into your OS' security keychain 2018-06-26 10:15:27 -04:00
3b1321908e Merge pull request #295 from cytopia/upgrade-httpd-container
Use release httpd container (index: index.php index.html index.htm)
2018-06-23 23:15:55 +02:00
db25322daf Use tagged httpd versions 2018-06-23 20:48:52 +02:00
1cc9eb8a9c Use release httpd container 2018-06-23 17:45:32 +02:00
bb5c78d025 Merge pull request #294 from cytopia/fix-www-data-dir
Ensure data dir is available
2018-06-23 17:44:10 +02:00
0225d4aea8 Ensure data dir is available 2018-06-23 17:43:29 +02:00
39f7dc17b0 add z to everything
fixes #255

I tested on fedora 28
looks good to me
please test this on a non-SE Linux machine
it should not have any effect there
2018-06-07 20:31:29 -04:00
b3e4e6efdb Merge pull request #282 from cytopia/underscore-domains
Fix #224
2018-06-07 07:59:06 +02:00
c9c63743c5 Merge branch 'master' into underscore-domains
* master:
  Retry install on network outage
  Minor typo fix
  Minor typo fix
  Clean up travis-ci file
  Check documentation via travis
  Fix warnings
  Fix overlay scroll
  Clean out sphinx errors
  Fix table
2018-06-05 16:44:13 +02:00
b8b73fd6d9 Merge pull request #285 from acafourek/master
Minor typo fix in docs
2018-06-05 16:41:19 +02:00
76d136afac Merge pull request #284 from cytopia/documentation-fixes2
Retry install on network outage
2018-06-05 16:40:37 +02:00
9ac4a768d4 Retry install on network outage 2018-06-05 14:15:54 +02:00
3344f19b11 Merge pull request #1 from acafourek/patch-2
Minor typo fix
2018-06-04 22:15:36 -04:00
aa274a59d0 Merge pull request #2 from acafourek/patch-1
Minor typo fix
2018-06-04 22:15:31 -04:00
195ce98efc Minor typo fix 2018-06-04 22:14:24 -04:00
7cb99c62ef Minor typo fix 2018-06-04 22:13:36 -04:00
cbdc036422 Merge pull request #283 from cytopia/documentation-fixes
Documentation cleanup
2018-06-04 18:24:56 +02:00
a06e7d5ea1 Clean up travis-ci file 2018-06-04 10:30:13 +02:00
8f71c56a51 Check documentation via travis 2018-06-03 21:54:38 +02:00
5cf7a45638 Fix warnings 2018-06-03 20:17:21 +02:00
3ffcaf133c Fix overlay scroll 2018-06-03 20:05:33 +02:00
65497cb9d8 Clean out sphinx errors 2018-06-03 19:16:22 +02:00
b7b215b6f1 Fix table 2018-06-03 14:59:16 +02:00
c4fdf564b2 Fix #224 underscore domains for Apache 2018-06-03 14:03:56 +02:00
cd6319a102 Merge pull request #276 from cytopia/enable-disable-php-modules
#270 #263 Enable/Disable PHP Modules
2018-05-22 01:27:52 +02:00
5835f9d2ad Merge pull request #277 from cytopia/doc-codeignitor
Documentation: Setup CodeIgniter
2018-05-21 10:53:11 +02:00
ad532b3d98 Documentation: Setup CodeIgniter 2018-05-21 10:52:37 +02:00
a53d1ee0d6 #270 #263 Enable/Disable PHP Modules 2018-05-21 10:23:55 +02:00
1d9879d966 Merge pull request #272 from cytopia/update-docker
Add PHP 7.3 to update-docker script
2018-05-19 12:51:14 +02:00
5a518bac95 Add PHP 7.3 to update-docker script 2018-05-18 18:00:49 +02:00
2fc71eb8e3 Merge pull request #269 from cytopia/trust-ca-internally
Fix #259 Add CA as trusted entity to PHP container
2018-05-17 22:11:41 +02:00
55f8ab5e22 Merge pull request #268 from cytopia/photoncms
Documentation: how to install Photon CMS
2018-05-16 08:35:19 +02:00
dd92609cf8 Update Photon CMS documentation 2018-05-16 08:34:22 +02:00
9a561fe4ba Fix #259 Add CA as trusted entity to PHP container 2018-05-15 08:38:01 +02:00
1309037643 How to install Photon CMS 2018-05-15 00:30:00 +02:00
21e78ee0b9 Merge pull request #267 from cytopia/php-7.3
Adding: PHP-FPM 7.3
2018-05-14 23:31:09 +02:00
93024c39f1 Adding: PHP-FPM 7.3 2018-05-13 17:21:32 +02:00
ea0ec54aad Merge pull request #264 from cytopia/php-5.3
PHP-FPM 5.3
2018-05-12 20:40:06 +02:00
61d58dcf56 Fix up build jobs 2018-05-12 19:58:29 +02:00
87edcfdcdc Add PHP 5.3 support 2018-05-12 16:03:43 +02:00
58952f884a Bump version 2018-05-12 16:02:02 +02:00
6e7a622c88 Fix PHP syntax for PHP 5.3 2018-05-12 16:01:31 +02:00
8fa0e2a427 Merge pull request #257 from cytopia/doc-fix-toc
Fix ToC
2018-05-08 09:27:03 +02:00
9c1fc63bb7 Fix ToC 2018-05-08 09:26:24 +02:00
30a3246591 Merge pull request #256 from cytopia/doc-auto-dns
Fix #225 systemd-resolvd documentation
2018-05-08 09:07:00 +02:00
7ae2a75e59 Fix #225 systemd-resolvd documentation 2018-05-08 09:06:10 +02:00
f68621fd43 Merge pull request #253 from cytopia/documentation-updates
Documentation updates
2018-05-07 09:09:43 +02:00
8b31862b02 Clarify that all frameworks are supported 2018-05-07 09:09:06 +02:00
a5c980fb99 Extend feature section with SSL certificates 2018-05-07 09:08:37 +02:00
c4f099d9f3 Merge pull request #251 from echosa/patch-1
Correct typo in docs.
2018-05-07 08:46:01 +02:00
d2cffdfebe Merge pull request #252 from cytopia/fix-tools
Fix tools table
2018-05-07 01:02:47 +02:00
4915351421 Fix tools table 2018-05-07 01:02:20 +02:00
f0f13bb360 Correct typo in docs. 2018-05-06 17:24:08 -05:00
eecc791540 Merge pull request #239 from cytopia/https
Add HTTPS support
2018-05-06 11:10:37 +02:00
9f868c7e04 Merge pull request #249 from Remo/patch-1
add ssh to available tools
2018-05-05 23:03:11 +02:00
5c4c856b84 add ssh to available tools 2018-05-05 18:15:02 +02:00
04ddd07312 Merge pull request #247 from cytopia/variable-naming
Fix #242 variable naming
2018-05-05 17:13:08 +02:00
7fcd82be2a Fix #242 variable naming 2018-05-05 13:23:46 +02:00
9e469cdc72 Documentation: How to enable SSL on Firefox 2018-05-05 12:57:11 +02:00
ea08824172 Documentation: link HTTPS documentation 2018-05-05 12:56:36 +02:00
535a398bff Bump release version 2018-05-05 12:35:07 +02:00
02464bc6d5 README: HTTPS support via auto-generated SSL certificates 2018-05-05 12:35:02 +02:00
5a63ceb105 Documentation: SSL Certificates 2018-05-05 12:34:58 +02:00
44b4aa527a Lock to latest httpd server version 2018-05-05 12:34:53 +02:00
2f73e97f64 Update vhost-gen templates 2018-05-05 12:34:49 +02:00
b03a9a1ead Show SSL port in intranet page 2018-05-05 12:34:45 +02:00
05af938cb8 Make intranet SSL certificate CN configurable 2018-05-05 12:34:40 +02:00
42383489bd Update vhost-gen templates 2018-05-05 12:34:36 +02:00
91ba18f3bd Temporarily adding release tag for httpd container 2018-05-05 12:34:32 +02:00
0765c02aa5 Adjust env settings to match new HTTPD container 2018-05-05 12:34:28 +02:00
84c1729a81 Add HTTPS port 2018-05-05 12:34:23 +02:00
fdce2ebd8e Add Certificate Authority mount directory 2018-05-05 12:34:19 +02:00
d6cabd2e09 Ignore Certificate Authority from being added to git 2018-05-05 12:34:15 +02:00
c7b777dfb2 Send AJAX calls on http or https 2018-05-05 12:34:11 +02:00
6453954565 Merge pull request #243 from ortic/disable-mysql-general-log
disable mysql query log by default
2018-05-04 08:55:02 +02:00
3248c81c62 set default value for general log in documentation 2018-05-04 08:53:46 +02:00
c8c6f914c2 disable mysql query log 2018-05-03 20:16:02 +02:00
139dc7cec7 Merge pull request #237 from cytopia/documentation-dns
Release v0.13.1 (Communicate with external hosts)
2018-04-29 11:41:36 +02:00
5c57f8a1a7 Fix DNS issues with CNAME's 2018-04-28 16:28:13 +02:00
e7206f2e30 Merge pull request #238 from cytopia/fix-bind-version
Fix bind version in intranet
2018-04-28 16:27:36 +02:00
babefe4160 Fix bind version in intranet 2018-04-28 15:21:09 +02:00
8b50316787 Bump version 2018-04-28 15:13:37 +02:00
494cb061c3 Documentation: Communicate with external hosts 2018-04-28 12:17:07 +02:00
3aacd81d26 Be able to communicate with external hosts 2018-04-28 12:15:41 +02:00
e5ec9c5e44 Merge pull request #232 from cytopia/DVL-014-doc-env
Documentation for how to handle multiple env files
2018-04-25 01:03:14 +02:00
14d759d18b Merge pull request #231 from cytopia/DVL-014
Add documentation for #222 #229: Custom docker images
2018-04-25 01:02:35 +02:00
18a07a15f7 Fixes #145: Documentation for how to handle multiple env files 2018-04-25 00:41:13 +02:00
f0834dc9c5 Add documentation for #222 #229: Custom docker images 2018-04-25 00:24:47 +02:00
ba233165ab Merge pull request #229 from pedrosanta/compose-override-gitignore
Ignore 'docker-compose.override.yml'
2018-04-24 20:22:34 +02:00
79d4618345 Add docker compose override file to .gitignore
As documented on https://docs.docker.com/compose/extends it's possible
to use a docker-compose.override.yml file to override/extend
configurations of a docker-compose.yml. As such, this is an excellent
way for one to perform own/local tweaks and overrides without
changing/impacting project files. This adds a line for it on .gitignore.
2018-04-19 12:47:28 +01:00
8c121c5457 Merge pull request #226 from chrizz1001/patch-1
Typo in update doc
2018-04-17 11:27:24 +02:00
7bb469f3c7 Typo in update doc
# Ensure containers are stopped
   host> docker-compose ps
2018-04-17 08:51:13 +02:00
96041807a0 Merge pull request #203 from cytopia/new-php-container
REL-0.13: New PHP Container
2018-04-15 10:43:38 +02:00
068545a2a9 Intranet: Update phpMyAdmin to 4.8 2018-04-14 11:32:33 +02:00
e59bd1098f Intranet: Update Adminer to 4.6.2 2018-04-14 10:57:31 +02:00
88eb3ae68d Intranet: show new PHP mounts 2018-04-14 10:54:09 +02:00
b75e04dcab Documentation: available container 2018-04-14 10:51:53 +02:00
fbb475123f Add more container versions 2018-04-14 10:50:55 +02:00
3cf7321d3b Fix contributors link 2018-04-14 10:46:18 +02:00
7615dfa443 Bump version 2018-04-14 10:46:00 +02:00
2fbdd56a0d Documentation: remove build files 2018-04-14 10:17:59 +02:00
5eee20877a Documentation: Finish feature section 2018-04-14 10:17:58 +02:00
76a825b887 Documentation: Update legacy docs 2018-04-14 10:17:55 +02:00
2b1dc0efc2 Documentation: Xdebug for PHPStorm 2018-04-14 10:17:53 +02:00
a23b23b774 Documentation: Xdebug 2018-04-14 10:17:53 +02:00
8689bc993e Documentation: awesome-ci 2018-04-14 10:17:52 +02:00
9b3e3aa738 Documentation: Xdebug - first draft 2018-04-14 10:17:51 +02:00
e713c72bfa Fix loading times to find available services 2018-04-14 10:17:50 +02:00
b5c3b13dce Make PHP-FPM follow log behaviour from .env 2018-04-14 10:17:50 +02:00
0570e2cdf2 Remove file from git 2018-04-14 10:17:49 +02:00
17fd7108f1 Make PHP-FPM configurable 2018-04-14 10:17:48 +02:00
7b4b2370ff Documentation: #217 add best-practice hostnames for php config 2018-04-14 10:17:47 +02:00
271313c025 Documentation: custom env variables 2018-04-14 10:17:46 +02:00
e09ff53d58 Documentation: best-practice 2018-04-14 10:17:45 +02:00
d6a58ff1ac Documentation: apache.conf 2018-04-14 10:17:45 +02:00
474b8b2121 Documentation: nginx.conf 2018-04-14 10:17:44 +02:00
04812a5131 Documentation: typo fix 2018-04-14 10:17:43 +02:00
86b4247b81 Documentation: #212 MySQL configuration files on Docker Toolbox 2018-04-14 10:17:42 +02:00
63fa5e6811 Add Documentation build badge 2018-04-14 10:17:42 +02:00
d7a2bcb266 Documentation: config files 2018-04-14 10:17:41 +02:00
f5cc9bcee6 Documentation: bashrc.sh 2018-04-14 10:17:40 +02:00
618e485460 Documentation: Configuration files 2018-04-14 10:17:39 +02:00
6424e6e426 Documentation: Backup and Restore MongoDB 2018-04-14 10:17:39 +02:00
cc1ce40858 Documentation: Backup and Restore PostgreSQL 2018-04-14 10:17:38 +02:00
474565a66d Documentation: Backup and Restore PostgreSQL 2018-04-14 10:17:37 +02:00
a6348344f1 Documentation: Backup and Restore MySQL 2018-04-14 10:17:36 +02:00
4012bfd2cf Documentation: hacking 2018-04-14 10:17:36 +02:00
3d4b3e059d Documentation: Backup and Restore MySQL 2018-04-14 10:17:35 +02:00
2a4316079a Documentation: various 2018-04-14 10:17:34 +02:00
b445e9f4e2 Documentation: FAQ 2018-04-14 10:17:33 +02:00
50904504cf Documentation: Troubleshooting 2018-04-14 10:17:32 +02:00
4f8e5ee948 Documentation: artwork 2018-04-14 10:17:31 +02:00
7f9771081a Documentation: Devilbox intranet 2018-04-14 10:17:30 +02:00
64b08f61bf Documentation: Email catch-all 2018-04-14 10:17:30 +02:00
794f037727 Documentation: change images 2018-04-14 10:17:29 +02:00
4502497371 Documentation: Docker logs 2018-04-14 10:17:28 +02:00
7d184a5e55 Documentation: php.ini 2018-04-14 10:17:27 +02:00
08ebab728c Documentation: php.ini 2018-04-14 10:17:27 +02:00
d9bb7419cc Documentation: vhost-gen 2018-04-14 10:17:26 +02:00
099751a8b9 Documentation: Auto-DNS 2018-04-14 10:17:25 +02:00
7d5e4feada Documentation: DNS 2018-04-14 10:17:24 +02:00
33082a98ed Documentation: Auto-DNS 2018-04-14 10:17:24 +02:00
71899930aa Documentation: Examples 2018-04-14 10:17:23 +02:00
f6ac5fc776 Cleanup 2018-04-14 10:17:22 +02:00
a621d4b6f7 documentation: work inside the PHP container 2018-04-14 10:17:21 +02:00
6f79f007de Change container versions 2018-04-14 10:17:21 +02:00
08bc17d186 Warning about use of localhost as TLD 2018-04-14 10:17:20 +02:00
a562c85dac Finalize subdomains 2018-04-14 10:17:19 +02:00
ed2d12dbba Adding vhost-gen templates 2018-04-14 10:17:18 +02:00
2c69626a1d Stashing changes 2018-04-14 10:17:17 +02:00
ea7b2c9499 Minor wording fixes 2018-04-14 10:17:16 +02:00
5f61d9d8e6 Add available tools 2018-04-14 10:17:16 +02:00
83a3829206 How to enter the PHP container 2018-04-14 10:17:15 +02:00
5fec8a7e09 Do not add sphinx builds to git 2018-04-14 10:17:14 +02:00
8bd7dd6157 Finalize env-file documentation 2018-04-14 10:17:13 +02:00
68636deeaf Extend env file documentation 2018-04-14 10:17:13 +02:00
b1f0e12111 Extend env file documentation 2018-04-14 10:17:12 +02:00
c587e97eba Extend env file documentation 2018-04-14 10:17:11 +02:00
9b41a2468c Info about .env file 2018-04-14 10:17:10 +02:00
dc641b9298 Add files to ToC 2018-04-14 10:17:10 +02:00
75236067e5 Fix typos 2018-04-14 10:17:09 +02:00
d56a7db02a Update about section 2018-04-14 10:17:08 +02:00
7de5103fcc Address permission problem 2018-04-14 10:17:07 +02:00
ca002781c2 Add stale files to index 2018-04-14 10:17:06 +02:00
107f689595 Finalize getting-started-guide 2018-04-14 10:17:06 +02:00
5a29be3f92 Extend documentation 2018-04-14 10:17:04 +02:00
2180e8a287 Extend getting started guide 2018-04-14 10:17:03 +02:00
41d22a804d getting started 2018-04-14 10:17:03 +02:00
b5ced99621 Getting started 2018-04-14 10:17:02 +02:00
fc791c497d Setup menu 2018-04-14 10:17:01 +02:00
76936c9afd Add theme options 2018-04-14 10:17:00 +02:00
0f28572ef1 Add imports 2018-04-14 10:16:59 +02:00
a5f7e4885d Add markdown support 2018-04-14 10:16:58 +02:00
10459db183 Update index 2018-04-14 10:16:58 +02:00
77950f77bc conf.py theme 2018-04-14 10:16:57 +02:00
f0192cce73 Build in RST format 2018-04-14 10:16:56 +02:00
e215dd610e Fix extensions 2018-04-14 10:16:55 +02:00
e32fad5185 Fix build error 2018-04-14 10:16:54 +02:00
43235e69ba Fix build error 2018-04-14 10:16:54 +02:00
6fd9ea1b72 Add quickstart 2018-04-14 10:16:53 +02:00
9110dd0f38 Installation subdir 2018-04-14 10:16:52 +02:00
7aecaa22ba Adding index 2018-04-14 10:16:51 +02:00
5c0f778666 Adding configuration file 2018-04-14 10:16:50 +02:00
e1e60c736e Adjust date 2018-04-14 10:16:50 +02:00
e73604dfb5 Fixing #206: change docroot to subdir 2018-04-14 10:16:49 +02:00
5a23138268 Update update-docker.sh 2018-04-14 10:16:48 +02:00
5c89cd2fe4 Update travis tests 2018-04-14 10:16:47 +02:00
ab7e3b7279 Integrate new PHP container 2018-04-14 10:16:46 +02:00
dcad1b2387 Add new PHP container namespace 2018-04-14 10:16:45 +02:00
abb7b8dd5d Merge pull request #204 from kerrizor/patch-1
typo
2018-03-07 21:59:50 +01:00
2465e29628 typo 2018-03-06 16:15:58 -08:00
51e951ef3b Merge pull request #200 from codetriage-readme-bot/codetriage-badge
Add CodeTriage badge to cytopia/devilbox
2018-03-04 13:34:40 +01:00
7f1fc72e3e Merge pull request #201 from pbearne/master
Added shell.bat to box access on windows
2018-03-01 14:55:32 +01:00
d9fe19a8d7 Added window shell.bat instructions 2018-03-01 08:06:00 -05:00
cc73cefd3f Create shell.bat
shell for windows
2018-03-01 08:02:02 -05:00
f3ce95b6b8 Merge pull request #199 from xmarkclx/patch-2
Add Mac Instructions on Making Auto-DNS Work
2018-02-27 22:06:18 +01:00
7b190170c5 Add CodeTriage badge to cytopia/devilbox
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/cytopia/devilbox/badges/users.svg)](https://www.codetriage.com/cytopia/devilbox)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly about 1 year ago, [cytopia](https://github.com/cytopia) added this project to CodeTriage in order to start contributing.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![Email clients like GMAIL do not render SVG images](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-26 14:08:06 -06:00
c7071e527e Update Configure.md 2018-02-26 17:37:56 +08:00
34e946e50f Merge pull request #185 from cytopia/release-0-12-1
Release v0.12.1
2018-01-31 17:14:08 +01:00
2df763d147 Merge pull request #184 from irhen/fixing-typos
Update Configure.md
2018-01-30 19:29:23 +01:00
e26bae0d83 Bump date and version 2018-01-30 15:36:04 +01:00
6dcde6b1b7 Have Bind bound to a specific tag to make sure it is stable 2018-01-30 15:30:59 +01:00
8726acfb5a Update Configure.md
fix some typos
2018-01-30 17:21:39 +03:00
996874daa1 Merge pull request #181 from mwmllr/DVL-013
DVL-013 removing invalid option from quick start docker-composer remo…
2018-01-28 17:37:26 +01:00
1e001b616a DVL-013 removing invalid option from quick start docker-composer removal in the docs 2018-01-25 21:21:28 +01:00
865860affe Merge pull request #172 from noplanman/patch-1
Copy-Paste fix, typos
2017-12-30 00:06:47 +01:00
2c4fd49478 Copy-Paste fix, typos 2017-12-29 18:53:31 +00:00
909d72dbbe Merge pull request #164 from Cipa/master
body might be in a different spot
2017-12-18 07:52:24 +01:00
382d7001e1 email body detection improvments 2017-12-08 07:17:07 -08:00
514fab16e3 Merge pull request #165 from cytopia/DVL-013-doc-fixes
Dvl 013 doc fixes
2017-12-07 11:47:26 +01:00
d1bbd5d92b DVL-013 Link Date statement in PR template 2017-12-07 09:35:43 +01:00
3f5555ee19 DVL-013 Fix typo in PR template 2017-12-07 09:34:04 +01:00
38460eaa1a DVL-013 Improve docs: work inside the container 2017-12-07 09:32:09 +01:00
033ed60148 DVL-013 #163 Extend Auto-DNS documentation 2017-12-07 09:15:52 +01:00
e0e37bb64d DVL-013 Adjust Pull Request template 2017-12-07 08:42:07 +01:00
1f8390c8a6 DVL-013 Bump date 2017-12-07 08:41:49 +01:00
00c43bf8b7 DVL-013 Show Auto-DNS in documentation ToC 2017-12-07 08:41:33 +01:00
708962647c body be in a diffrent spot
When sending email with codeigniter the body is inside $structure->parts.

I should look into what mail objects variants are out there.
2017-12-06 11:17:05 -08:00
654b6375fb Merge pull request #162 from Cipa/master
mail improvments
2017-12-06 08:22:58 +01:00
f1ed392b94 mail improvments
- html email by default
- Raw source button
- extra from column
2017-12-05 20:04:33 -08:00
2381b5b5fb Merge pull request #156 from alexmanno/correct_typo_in_readme
Correct typo on README.md
2017-11-24 21:41:12 +01:00
4107481747 Correct typo on README.md 2017-11-24 21:28:51 +01:00
3c1cf64b15 Merge pull request #153 from cytopia/DVL-013-http-port
DVL-013 Fix #151 Use correct Httpd port in intranet
2017-11-21 09:02:42 +01:00
5a0b275610 DVL-013 Fix #151 Use correct Httpd port in intranet 2017-11-21 09:01:15 +01:00
930bb1c7fc Merge pull request #141 from cytopia/DVL-013-memcd-fixes
DVL-013 Handle false values retrieved from Memcached
2017-11-07 00:43:32 +01:00
776ec5d517 DVL-013 Handle false values retrieved from Memcached 2017-11-05 19:00:34 +01:00
959aa29f92 Merge pull request #140 from cytopia/DVL-013-intranet-fixes
Dvl 013 intranet fixes
2017-11-04 17:40:40 +01:00
e254d01a65 DVL-013 Fix error handling in logger 2017-11-04 13:42:41 +01:00
aaaab931b7 DVL-013 Sort Feature list 2017-11-04 13:42:15 +01:00
e79eb87cbb Merge pull request #137 from cytopia/DVL-013
WIP: DVL-013 Logos and layout
2017-10-16 17:56:22 +02:00
b42e3eb964 DVL-013 Remove battery logos 2017-10-16 17:53:33 +02:00
23b6ac07be DVL-013 Update dash graphics 2017-10-16 17:47:27 +02:00
051d723d13 DVL-013 Remove unneeded images 2017-10-16 17:12:32 +02:00
ab3df0c5dc DVL-013 Shorten README 2017-10-16 13:56:49 +02:00
aac3da3111 DVL-013 Fix markdown 2017-10-16 11:33:43 +02:00
0f1de08356 DVL-013 Logos and layout 2017-10-16 09:17:27 +02:00
c04fa23578 Merge pull request #130 from cytopia/REL-0.12
Rel 0.12
2017-10-10 15:45:38 +02:00
062aa18730 REL-0.12 Fix bold headline 2017-10-10 09:13:12 +02:00
1fa6bc7008 REL-0.12 Bump version for upcoming release 2017-10-10 08:56:10 +02:00
5fce8da961 REL-0.12 Revert Xdebug port back to 9000 2017-10-08 12:27:31 +02:00
bb2288a461 REL-0.12 Update new versions of available Docker container 2017-10-08 12:17:36 +02:00
f454a032c9 REL-0.12 Doc: How to setup Joomla 2017-10-03 12:45:37 +02:00
cc0c947d6b REL-0.12 Remove fixed note about uid/gid 2017-10-03 11:58:42 +02:00
c87201db13 REL-0.12 Bump version 2017-10-03 11:50:09 +02:00
5bd184c609 REL-0.12 Doc: How to customize the web server configuration 2017-10-03 11:49:16 +02:00
6f00608fba REL-0.12 Doc: #128 How to add custom environment variables 2017-10-03 11:43:57 +02:00
352a8d3b40 REL-0.12 Doc: How to customize per project vhost 2017-10-03 11:38:39 +02:00
2b5336c342 REL-0.12 Doc: How to change the htdocs directory name 2017-10-03 11:28:42 +02:00
54bddc820a REL-0.12 Doc: How to disable the Intranet 2017-10-03 11:07:18 +02:00
8ad5b4ef61 REL-0.12 Default to listen on all Interfaces 2017-10-03 10:32:23 +02:00
5d11a09866 REL-0.12 Fix version getter 2017-10-02 13:00:48 +02:00
3990d2de71 REL-0.12 Speed up frontpage by using Ajax requests 2017-10-02 12:42:29 +02:00
20383fee48 REL-0.12 Update update-docker.sh to use new httpd namespace 2017-10-01 19:16:09 +02:00
fb193aba20 DVL-012 Switch httpd Docker namespace 2017-10-01 18:59:11 +02:00
f5b03f22b7 REL-0.12 Make document root dir dynamic 2017-09-28 16:31:33 +02:00
0cb54d34ef REL-0.12 Remove quotes from variable values 2017-09-28 16:30:51 +02:00
32add6d2a0 REL-0.12 Use custom doc root directory in Intranet 2017-09-28 16:30:00 +02:00
bf0bc75b90 REL-0.12 Evade cross domain requests via POST 2017-09-27 14:42:42 +02:00
d8e60644e8 REL-0.12 Remove deprecates from docker-compose.yml 2017-09-26 19:56:28 +02:00
4ad3596daa REL-0.12 #128 Source environment variables 2017-09-26 19:53:31 +02:00
9752af1363 REL-0.12 Add directories to globally configure web servers 2017-09-26 19:39:38 +02:00
769b34c3e6 REL-0.12 Set correct httpd status page 2017-09-26 17:44:31 +02:00
69bb14288d REL-0.12 Enable devilbox intranet by default 2017-09-26 17:43:41 +02:00
c58b1e3db3 REL-0.12 Add option to disable devilbox Intranet 2017-09-26 16:58:24 +02:00
1ad6de7e4c REL-0.12 Attach new nginx Docker container 2017-09-26 16:51:49 +02:00
cac8a17bb6 Merge pull request #124 from cytopia/DVL-012-adminer
DVL-012 Fix #97: Open Adminer in new window to overcome UI glitches
2017-09-10 11:54:40 +02:00
4bbea8f134 Merge pull request #127 from cytopia/DVL-012-password-protection
DVL-012 Password protect the devilbox intranet
2017-09-10 11:54:16 +02:00
19908307d6 DVL-012 Add documentation for how to password protect 2017-09-09 14:16:04 +02:00
63e1acc02a DVL-012 #121 Password protect the devilbox intranet 2017-09-09 10:40:07 +02:00
dd34e4780e DVL-012 Fix #97: Open Adminer in new window to overcome UI glitches 2017-09-09 08:29:22 +02:00
0c4290b0c4 Merge pull request #115 from cytopia/DVL-012-customise-bash
DVL-012 be able to customize bash config files
2017-08-18 20:23:26 +02:00
87b7219901 DVL-012 Documentation: Customize bash and vim 2017-08-18 09:14:33 +02:00
bbfd938001 Merge pull request #114 from cytopia/DVL-012-requirements
DVL-012 Name correct required Docker version in documentation
2017-08-18 08:40:40 +02:00
e8975ec92c Merge pull request #113 from cytopia/DVL-012-fix-dns-forwarder
DVL-012 #112 Fixes wrong docker-compose var for BIND
2017-08-18 08:39:55 +02:00
bb0a15f4e6 DVL-012 be able to customize bash config files 2017-08-17 21:20:41 +02:00
8f75590e8d DVL-012 Name correct required Docker version in documentation 2017-08-17 08:37:53 +02:00
4cabfeccec DVL-012 #112 Fixes wrong docker-compose var for BIND 2017-08-17 08:30:18 +02:00
5c22c045a1 Merge pull request #111 from cytopia/DVL-012-awesome-ci-fix
DVL-012 Fix ToC on README.md
2017-08-16 23:29:13 +02:00
f5792f1bad DVL-012 Fix ToC on README.md 2017-08-16 20:23:59 +02:00
4181805ff2 Merge pull request #110 from cytopia/DVL-012-awesome-ci
DVL-012 Add documentation for awesome-ci
2017-08-16 20:20:24 +02:00
b6be233241 DVL-012 Fix ToC 2017-08-16 09:21:48 +02:00
b2ebe2df0a DVL-012 Add documentation for awesome-ci 2017-08-16 09:16:58 +02:00
77fb8d50d1 Merge pull request #108 from cytopia/DVL-012-custom-php-modules
DVL-012 #107 Allow to load custom PHP modules
2017-08-16 08:12:03 +02:00
b7fd5a01e1 Merge pull request #100 from cytopia/DVL-012
WIP: DVL-012 Fix #97 Devilbox UI footer overlaps embedded tools
2017-08-13 14:02:11 +02:00
bcfa689fab DVL-012 Documentation: Add ToC for FAQ section 2017-08-13 13:56:37 +02:00
e2c724ce23 DVL-012 Documentation: How to load custom PHP modules 2017-08-13 13:36:24 +02:00
d6bf969212 DVL-012 #107 Allow to load custom PHP modules 2017-08-12 11:05:39 +02:00
9545113e43 DVL-012 Fix #97 Devilbox UI footer overlaps embedded tools 2017-07-22 11:43:07 +02:00
817a942bba Merge pull request #98 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2017-07-22 10:01:41 +02:00
def3636196 Add Gitter badge 2017-07-21 08:49:17 +00:00
1b143eb222 Merge pull request #95 from cytopia/DVL-012
DVL-012 Stop all container during travis checks
2017-07-09 14:33:53 +02:00
2faf541c93 DVL-012 Stop all container during travis checks 2017-07-08 14:16:55 +02:00
358d3e6ca5 Merge pull request #94 from cytopia/DVL-012
DVL-012 #92 Adds documentation for changing data directories
2017-07-05 08:18:24 +02:00
dd750f88ad DVL-012 Add datadir change info in env-example 2017-07-05 08:12:07 +02:00
5a9fce85a2 DVL-012 #92 Adds documentation for changing data directories 2017-07-04 09:00:29 +02:00
df915f8ebb Merge pull request #91 from cytopia/DVL-012
DVL-012 Fix contradictory TLD_SUFFIX documentation to default to *.loc
2017-07-03 20:14:17 +02:00
d9a0083edd Merge pull request #93 from kodemaan/patch-1
Update README.md
2017-07-03 20:00:57 +02:00
742f7decee Update README.md 2017-07-03 11:19:10 -04:00
6a9d248c4a DVL-012 Fix contradictory TLD_SUFFIX documentation to default to *.loc 2017-07-03 08:53:48 +02:00
d4d3e1223d Merge pull request #89 from cytopia/DVL-012
DVL-012 Adding PerconaDB
2017-07-02 10:54:40 +02:00
e560fe5712 DVL-012 Add more info about supported frameworks 2017-07-02 10:52:31 +02:00
0073374d91 DVL-012 Harden composer-download for travis tests 2017-07-02 10:20:54 +02:00
1a3b9e03cf DVL-012 Fix domain mixup in Examples 2017-07-01 21:03:11 +02:00
0b609be2fe DVL-012 Adding PerconaDB 2017-07-01 18:54:09 +02:00
812b0eface Merge pull request #88 from cytopia/DVL-012
DVL-012 Howto setup laravel
2017-07-01 15:59:34 +02:00
4990931c3c DVL-012 Howto setup laravel 2017-07-01 12:40:59 +02:00
fd7a19c9b1 Merge pull request #87 from cytopia/DVL-012
REL-0.12 Making devilbox ready for PHP 7.2
2017-06-27 18:19:49 +02:00
4ea1aa2370 REL-0.12 Making devilbox ready for PHP 7.2 2017-06-27 13:14:02 +02:00
ba498cad2a Merge pull request #86 from cytopia/DVL-012
DVL-012
2017-06-26 13:15:42 +02:00
af5d5bbcba DVL-0.12 Fixing ToC links 2017-06-26 13:05:15 +02:00
f190b64766 DVL-0.12 Binding latest images to docker-compose 2017-06-26 11:19:28 +02:00
8fbc86f410 Merge pull request #85 from cytopia/release-0.11
REL-0.11 Fix ToC indentation
2017-06-25 14:59:55 +02:00
fc9038cd62 REL-0.11 Fix ToC indentation 2017-06-25 14:58:55 +02:00
fbb169c37c Merge pull request #81 from cytopia/release-0.11
Release 0.11
2017-06-25 14:47:26 +02:00
bd150c9606 REL-0.11 Show versions in intranet 2017-06-25 14:44:51 +02:00
72598ad05f REL-0.11 Bump intranet version date 2017-06-25 13:59:34 +02:00
e0b5a8f22a REL-0.11 OS differences 2017-06-25 13:57:29 +02:00
294cb75e4d REL-0.11 Link documentation into main README 2017-06-25 13:46:50 +02:00
5b66c3ef0c REL-0.11 Attaching tagged docker container 2017-06-22 12:31:35 +02:00
025c998350 REL-0.11 Updating intranet release version 2017-06-22 12:16:52 +02:00
f965f7ea44 REL-0.11 Auto-DNS documentation 2017-06-22 12:09:58 +02:00
0430331123 REL-0.11 Switch to new travis environment 2017-06-22 11:34:38 +02:00
66b58e5960 REL-0.11 Configure documentation 2017-06-22 11:32:43 +02:00
89524f5341 REL-0.11 Configuration Documentation 2017-06-21 19:10:26 +02:00
e6a3c531b5 REL-0.11 Documentation about MySQL|MariaDB Configuration 2017-06-21 18:52:37 +02:00
d4c27860f3 REL-0.11 Adding configure documentation 2017-06-21 18:18:43 +02:00
474c198166 REL-0.11 Default PHP/HHVM example ini files 2017-06-21 09:20:19 +02:00
19ce82deb9 REL-0.11 Configure documentation 2017-06-21 09:19:51 +02:00
c25a3bfed9 REL-0.11 Fixing #82 TCP/53 and UDP/53 already taken on OSX/Linux 2017-06-20 21:33:24 +02:00
f2033556e3 REL-0.11 Adding more Framework examples for documentation 2017-06-20 21:31:00 +02:00
947136a383 REL-0.11 Configuration documentation 2017-06-20 12:16:27 +02:00
5bd9d312b2 REL-0.11 Separate MongoDB data dir by versions 2017-06-20 12:16:27 +02:00
bab0c9707f REL-0.11 Framework example documentation 2017-06-20 12:16:27 +02:00
880895e73a REL-0.11 Backup documentation 2017-06-20 12:16:27 +02:00
4d3281cf4b REL-0.11 docker-compose ready for mysqldump-secure 2017-06-20 12:16:27 +02:00
8bcaa75283 REL-0.11 Updating documentation 2017-06-20 12:16:27 +02:00
3bbf6a042d REL-0.11 Ignoring *.swm files 2017-06-20 12:16:27 +02:00
dec304a40b REL-0.11 Updating release info 2017-06-20 12:16:27 +02:00
1c0f7adf13 REL-0.11 Changing default Bind port from 53 to 1053 2017-06-20 12:16:27 +02:00
57d17a5ca8 DVL-016 Usage documentation 2017-06-20 12:16:27 +02:00
f435fac2a0 DVL-016 Usage documentation 2017-06-20 12:16:27 +02:00
1fb4a4a53b DVL-16 Finalized doc structure 2017-06-20 12:16:27 +02:00
221ebcc8ff DVL-016 Info about docker logs 2017-06-20 12:16:27 +02:00
11242dac1f DVL-016 Run the devilbox 2017-06-20 12:16:27 +02:00
6e14f36735 DVL-016 Overview 2017-06-20 12:16:27 +02:00
e2b44d2a55 DVL-016 Hacking the devilbox 2017-06-20 12:16:27 +02:00
476cb55d23 DVL-016 Technical documentation 2017-06-20 12:16:27 +02:00
6f35ce264d DVL-016 Documentation structure 2017-06-20 12:16:27 +02:00
7370a2f52b DVL-016 Documentation FAQ 2017-06-20 12:16:27 +02:00
d70879ea9e DVL-016 Documentation Intro page 2017-06-20 12:16:27 +02:00
a8c1513bb7 DVL-016 clean-up after gh-pages branch 2017-06-20 12:16:27 +02:00
0cb044e39d Merge pull request #80 from ilsenem/feature-nginx-query-string
Fix query string truncation in nginx configuration
2017-06-20 11:48:04 +02:00
22ec70cd72 Fix query string truncation in nginx configuration 2017-06-16 13:16:38 +07:00
b5256e2a2b Merge pull request #72 from cytopia/DVL-015
DVL-015 Extend documentation
2017-05-28 13:44:28 +02:00
6cde13127d DVL-015 Extend documentation 2017-05-28 13:43:41 +02:00
23a5a5f38c Merge pull request #69 from cytopia/DVL-014
DVL-014 Cleaning Jekyll config
2017-05-27 19:00:08 +02:00
b69274649a DVL-014 Cleaning Jekyll config 2017-05-27 18:59:27 +02:00
a33521b8bc Merge pull request #68 from cytopia/DVL-014
DVL-014 Resize logos to appropriate size
2017-05-27 17:51:47 +02:00
76a5765552 DVL-014 Resize logos to appropriate size 2017-05-27 17:50:38 +02:00
024647af46 Merge pull request #67 from cytopia/DVL-014
DVL-014 Add gh-pages
2017-05-27 17:41:22 +02:00
e7d8c9a538 DVL-014 Add gh-pages 2017-05-27 17:39:33 +02:00
f7e633eda7 Create CNAME 2017-05-26 15:45:22 +02:00
2d24f80cb0 Merge pull request #66 from cytopia/DVL-013
DVL-013 Remove git submodule dependencies in phpMyAdmin
2017-05-26 14:22:08 +02:00
075c26e097 DVL-013 Remove git submodule dependencies in phpMyAdmin 2017-05-26 14:18:14 +02:00
da04b3ac06 Set theme jekyll-theme-slate 2017-05-26 14:01:23 +02:00
d09a588359 Merge pull request #62 from cytopia/release-0.10
Release v0.10
2017-05-26 13:53:15 +02:00
fac2025154 REL-0.10 Re-order env-example file 2017-05-26 09:02:16 +02:00
0f2beffdf4 REL-0.10 increment release date 2017-05-26 08:43:24 +02:00
442db787d7 REL-0.9 Bullet proof travis checks 2017-05-26 08:36:16 +02:00
0c5efeca3b REL-0.10 Fix actual version output 2017-05-25 13:41:26 +02:00
e82f1b1266 REL-0.10 Pad actual version display in travis checks 2017-05-25 12:58:15 +02:00
107af77189 REL-0.10 Show docker version during tests 2017-05-25 12:43:50 +02:00
93f03adc58 REL-0.10 Optimize travis checks to be extended in the future 2017-05-25 11:00:36 +02:00
c4b067a10f Rel-0.10 attach tagged bind container 2017-05-25 10:19:42 +02:00
c18c1d66a9 REL-0.10 Adding ability to use custom DNS resolver 2017-05-24 09:31:03 +02:00
5d556fc310 REL-0.10 Cleanup shell scripts 2017-05-24 08:45:53 +02:00
98b0fa8c64 REL-0.10 Clean travis tests 2017-05-24 08:37:37 +02:00
de5c9d6398 REL-0.10 Move doc/ folder to docs/ 2017-05-24 08:05:10 +02:00
3f6d3ee36b REL-0.10 Attach tagged php container 2017-05-24 08:00:53 +02:00
fdfc06d29d REL-0.10 Harden travis checks 2017-05-23 22:56:39 +02:00
38cab08d72 Set theme jekyll-theme-merlot 2017-05-23 13:35:21 +02:00
3dfa4a8cd9 Set theme jekyll-theme-cayman 2017-05-23 13:32:11 +02:00
9c2c91f165 REL-0.10 Improve README 2017-05-23 09:13:40 +02:00
c266e2dcde REL-0.10 Bump release date 2017-05-23 09:01:50 +02:00
17f6d34211 REL-0.10 Updating documentation 2017-05-23 08:47:45 +02:00
234804efe8 REL-0.10 Adding env file for MongoDB 2017-05-22 23:23:05 +02:00
05cdb4c3c1 REL-0.10 Adding MongoDB 2017-05-22 23:20:20 +02:00
0c643f3632 Merge pull request #58 from cytopia/release-0.9
Release 0.9
2017-05-21 22:37:28 +02:00
7330852b6b REL-0.9 Default to uid 1000 2017-05-21 22:09:03 +02:00
89ce45be6c REL-0.9 Attach tagged docker container 2017-05-21 14:14:49 +02:00
aff160a07f REL-0.9 Slight documentation improvements 2017-05-21 13:10:37 +02:00
f587156df1 REL-0.9 Final test with latest containers before tagging 2017-05-21 11:31:08 +02:00
0a44a49647 REL-0.9 Documentation table 2017-05-21 11:29:04 +02:00
7db119748b REL-0.9 Info about PS1 2017-05-20 21:55:22 +02:00
f419a65376 REL-0.9 How to enter the php container 2017-05-20 21:50:38 +02:00
9c689a5e2d REL-0.9 Improve documentation 2017-05-20 21:39:57 +02:00
640dd23f73 REL-0.9 Update README.md 2017-05-20 21:24:04 +02:00
24e2767f33 REL-0.9 Updating documentation 2017-05-20 20:13:14 +02:00
9d185a985b REL-0.9 Using short-hand name for memcached server 2017-05-20 20:12:31 +02:00
02a25ede19 REL-0.9 add new memcached version 2017-05-20 18:24:47 +02:00
44cf550778 REL-0.9 Increase version string 2017-05-20 16:34:07 +02:00
d292ed6be3 REL-0.9 Make travis easier to read 2017-05-20 16:33:06 +02:00
d7289a3f18 REL-0.9 Make PHP-7.0 the default 2017-05-20 16:24:37 +02:00
6d7908099d REL-0.9 Attach new mysql container versions 2017-05-17 15:24:49 +02:00
8052780520 REL-0.9 Get rid of volumes to be more compatible to windows 2017-05-17 13:38:11 +02:00
ae96dafdf5 REL-0.9 Fixing opcache gui jquery lib 2017-05-17 09:59:52 +02:00
ce70d76743 REL-0.9 Fix mysql custom config dir writeability 2017-05-17 09:38:29 +02:00
10aa233cb4 REL-0.9 Fix typo in travis 2017-05-17 09:24:09 +02:00
3d932398aa REL-0.9 Adding missing travis test function 2017-05-17 09:20:50 +02:00
f1b6ffae73 REL-0.9 Fix typo in travis scripts 2017-05-17 09:12:51 +02:00
b74cd69305 REL-0.9 Merge old and new travis checks 2017-05-17 09:05:10 +02:00
967ab54075 REL-0.9 Allow some services to fail in travis 2017-05-17 08:45:31 +02:00
26785ac448 REL-0.9 Re-enable new travis checks 2017-05-17 08:37:36 +02:00
6c59070afb REL-0.9 Webserver configuration fixes 2017-05-16 20:44:59 +02:00
4f03b54463 REL-0.9 Evaluate docker-internal and host DNS problems 2017-05-16 20:44:59 +02:00
b01777e22c REL-0.9 Intranet clean-up 2017-05-16 20:44:59 +02:00
1a6621475a REL-0.9 nginx config clean-up 2017-05-16 20:44:59 +02:00
2973fcacb0 REL-0.9 Indentation fix 2017-05-16 20:44:59 +02:00
f1b88a9c60 REL-0.9 Intranet refactoring 2017-05-16 20:44:59 +02:00
83ab3d8758 REL-0.9 Properly check client-side DNS via ajax CSR calls 2017-05-16 20:44:36 +02:00
d6fd9d1cda REL-0.9 Fix DNS vHost check 2017-05-16 20:44:36 +02:00
21ce41e6f3 REL-0.9 Clean up tests 2017-05-16 20:44:36 +02:00
f8606aaa25 REL-0.9 Fix negative check 2017-05-16 20:44:05 +02:00
67d3f67d6c REL-0.9 Fix error counting 2017-05-16 20:43:52 +02:00
cc8b93606a REL-0.9 Adjust testing for new container 2017-05-16 20:43:52 +02:00
73ab1b679d REL-0.9 Re-add travis functions 2017-05-16 20:43:29 +02:00
cf53e1fb43 REL-0.9 Re-add debug testing fucntion 2017-05-16 20:43:29 +02:00
c3955ea34e REL-0.9 Remove return in DNS check 2017-05-16 20:43:29 +02:00
cce2ed885a REL-0.9 Add css classes for ok/err 2017-05-16 20:43:29 +02:00
43528a6327 REL-0.9 Update travis checks 2017-05-16 20:43:29 +02:00
d8209ef111 REL-0.9 travis with newer docker-compose version 2017-05-16 20:41:04 +02:00
9794cbde3c REL-0.9 travis with newer docker version 2017-05-16 20:40:41 +02:00
ccef616189 REL-0.9 Adding Bind (DNS Server) 2017-05-16 20:40:41 +02:00
baa2da8a3a REL-0.9 Improving documentation 2017-05-16 20:40:41 +02:00
f7893ead14 REL-0.9 Adding information about DNS status 2017-05-16 20:40:41 +02:00
dfa8ff99dc REL-0.9 Check if container are running 2017-05-16 20:40:24 +02:00
d9a255ae6a REL-0.9 Error checking in case some containers are not running 2017-05-16 20:40:24 +02:00
07145d40ba REL-0.9 Restructure navigation 2017-05-16 20:40:24 +02:00
0f0b7b90e5 REL-0.9 Fix navigation 2017-05-16 20:40:02 +02:00
4b0277a30d REL-0.9 Updating Adminer to latest version 2017-05-16 20:40:02 +02:00
2d7e51027b REL-0.9 Fix Redis/Memcached overview 2017-05-16 20:38:44 +02:00
0afeefd964 REL-0.9 Fixes #9 #10 DNS checks and custom domain suffix 2017-05-16 20:38:44 +02:00
54e00598cd REL-0.9 Better mass virtual hosting wildcards 2017-05-16 20:38:15 +02:00
bb0abf4794 REL-0.9 Update documentation 2017-05-16 20:38:15 +02:00
cc6474217b REL-0.9 Update env-example 2017-05-16 20:38:15 +02:00
be55e9a6f4 REL-0.9 Variable interpolation with default values 2017-05-16 20:38:15 +02:00
90a65d8090 REL-0.9 Use hostnames instead of IP addresses 2017-05-16 20:38:15 +02:00
3f7fe50113 REL-0.9 Show version of installed toold 2017-05-16 20:38:15 +02:00
1c7c240874 REL-0.9 Update docker-compose 2017-05-16 20:38:15 +02:00
e1fe843299 REL-0.9 Updating README.md 2017-05-16 20:38:15 +02:00
04c079c625 REL-0.9 Adding docker entering scripts 2017-05-16 20:37:57 +02:00
ff39de09ef REL-0.9 Updating Intranet 2017-05-16 20:37:57 +02:00
a5cf4f9483 REL-0.9 Updating intranet class files 2017-05-16 20:36:59 +02:00
2f57691e58 REL-0.9 Adding separate documentation 2017-05-16 20:36:59 +02:00
e58dee3984 REL-0.9 Adding teather.js 2017-05-16 20:36:59 +02:00
09b935cfdd REL-0.9 Updating jquery 2017-05-16 20:36:59 +02:00
bbf1e3d2c1 REL-0.9 Updating bootstrap 2017-05-16 20:36:59 +02:00
629dbb0e50 DVL-013 Fix #49 Duplication of env variables passed to docker-compose 2017-05-16 20:36:59 +02:00
4c0ec7de3d Merge pull request #59 from cebe/patch-1
Fixed typo in .env file
2017-05-07 23:33:06 +02:00
20816fe831 Fixed typo in .env file
`MySQL` -> `PostgreSQL` in PostgreSQL section.
2017-05-07 23:04:17 +02:00
b20efd0e1a Merge pull request #43 from cytopia/DVL-008
DVL-008 Travis test all server combinations against each other
2017-05-06 14:38:32 +02:00
3d7f3f2c90 Merge pull request #55 from cytopia/DVL-014
DVL-014 Fix #54 - CP "Tools - Adminer" not working
2017-04-28 12:24:02 +02:00
beebb9ee3b DVL-014 Fix #54 - CP "Tools - Adminer" not working 2017-04-28 08:08:52 +02:00
dfa99dc174 Merge pull request #51 from lex111/patch-1
Small improvements in README.md
2017-04-26 20:32:38 +02:00
9e7a3b878b Small improvements in README.md 2017-04-25 21:22:03 +03:00
fea9ed9d31 DVL-008 Add newlines after .env info output 2017-04-23 21:23:13 +02:00
c2d664bcf5 DVL-008 Fix chosen server versions to test against 2017-04-23 21:23:13 +02:00
baac823ce6 DVL-008 Show settings nicely formatted 2017-04-23 21:23:13 +02:00
a6859394bf DVL-008 Show all other env settings 2017-04-23 21:23:13 +02:00
cbd98c1d28 DVL-008 Show current env settings 2017-04-23 21:23:13 +02:00
045b0d4801 DVL-008 Fix argument order 2017-04-23 21:23:13 +02:00
c55c440352 DVL-009 Change wait time from 90s to 30s 2017-04-23 21:23:13 +02:00
d82b4f0c0d DVL-008 Travis test all server combinations against each other 2017-04-23 21:23:13 +02:00
1cb00edd36 Merge pull request #47 from cytopia/DVL-012
DVL-012 Make custom cfg directories be persistent in git
2017-04-23 20:38:01 +02:00
2984ab5ed4 Merge pull request #46 from cytopia/DVL-011
DVL-011 Adding MariaDB 10.3
2017-04-23 20:37:41 +02:00
d094ea6388 Merge pull request #45 from cytopia/DVL-010
DVL-010 Make MySQL|PgSQL data dirs dynamic depending on version
2017-04-23 20:37:30 +02:00
a5a733c352 DVL-012 Make custom cfg directories be persistent in git 2017-04-23 17:34:35 +02:00
06dbf55a27 DVL-011 Adding MariaDB 10.3 2017-04-23 17:10:36 +02:00
54102a8b4c DVL-010 Make MySQL|PgSQL data dirs dynamic depending on version (opt container) 2017-04-23 16:11:24 +02:00
77492635d7 DVL-010 Make MySQL|PgSQL data dirs dynamic depending on version 2017-04-23 16:09:39 +02:00
8346db59a3 Merge pull request #44 from cytopia/DVL-009
DVL-009 Adding Redis docker container
2017-04-23 16:08:30 +02:00
4b1bc40307 DVL-009 Defaulting to Redis 3.2 2017-04-23 14:10:41 +02:00
e39c66cb8b DVL-009 Adding Redis DB page 2017-04-23 14:08:54 +02:00
c644913694 DVL-009 Adding Redis info page 2017-04-23 13:34:14 +02:00
2c8e56dd7a DVL-009 Adding Redis docker container 2017-04-23 13:20:32 +02:00
e344ff2243 Merge pull request #42 from cytopia/DVL-007
DVL-007 Fix gitignore and re-add ignored files
2017-04-22 13:26:49 +02:00
e555a5a90b Merge pull request #40 from cytopia/DVL-006
DVL-006 Adding MySQL 8.0
2017-04-22 12:39:25 +02:00
98e007a308 DVL-007 Fix gitignore and re-add ignored files 2017-04-22 11:58:17 +02:00
7858731dfe DVL-006 Adding devilbox custom mysql configuration 2017-04-21 23:17:59 +02:00
a9dc7c3c54 DVL-006 Info about latest feature 2017-04-21 22:27:37 +02:00
04c82c11c5 DVL-006 Adding MySQL 8.0 2017-04-21 22:25:02 +02:00
8fc5ff8be1 Merge pull request #39 from cytopia/DVL-005
DVL-005 Show log files on error
2017-04-21 22:18:31 +02:00
9b19cc0cf7 DVL-005 changing service combinations 2017-04-21 21:15:31 +02:00
311505beec DVL-005 Wait for url to become available 2017-04-21 19:38:36 +02:00
d8dd1c28d7 DVL-005 Intercept bad error codes during tests 2017-04-21 18:54:29 +02:00
7382aacf2a DVL-005 Use sudo to show logs on error 2017-04-21 11:40:19 +02:00
6eea97f1be DVL-005 Using non-persistent pg connect to prevent HHVM core-dump 2017-04-21 02:37:01 +02:00
8295e1ac18 DVL-005 Show log files on error 2017-04-21 02:07:45 +02:00
260eed9293 Merge pull request #38 from cytopia/DVL-004
DVL-004 use docker-compose updates
2017-04-20 18:55:13 +02:00
60b622c9f0 DVL-004 Revert to docker-compose version 2 2017-04-20 18:07:04 +02:00
f400c5b280 DVL-004 Use named volumes for container-only shared data (like sockets) 2017-04-20 17:47:27 +02:00
edf788f6dd DVL-004 use docker-compose version 2.1 2017-04-20 17:31:52 +02:00
e657e9b7e8 Merge pull request #36 from cytopia/DVL-002
DVL-002 Fix travis builds
2017-04-20 17:29:39 +02:00
81072dbfd7 DVL-002 Add docker-compose dependencies 2017-04-20 16:42:21 +02:00
cb512b4ac4 DVL-002 Prevent HHVM from segfaulting during pg_connect 2017-04-20 15:39:00 +02:00
567ba57a13 DVL-002 alter travis checks 2017-04-20 15:39:00 +02:00
2f96a1a349 Merge pull request #37 from cytopia/DVL-003
DVL-003 phpmyadmin-4.0 for PHP 5.4 and phpmyadmin-4.7 for everything …
2017-04-20 13:22:26 +02:00
5ea5fb9d79 DVL-003 phpmyadmin-4.0 for PHP 5.4 and phpmyadmin-4.7 for everything else 2017-04-20 12:55:30 +02:00
bc62d4e46c Merge pull request #35 from cytopia/DVL-001
DVL-001 Prepare HHVM support
2017-04-20 11:10:16 +02:00
b3aab7ddfc DVL-001 stop unwanted daemons 2017-04-19 20:09:42 +02:00
d396c921d7 DVL-001 Prepare HHVM support 2017-04-19 19:48:44 +02:00
294123505b add host port to intranet link (#34)
* add host port to intranet link

* display port on link
2017-03-25 10:36:39 +01:00
43d60ff90b Use other default stettings which work 2016-12-30 18:38:54 +01:00
8a5ca7bdc7 Merge branch 'hotfix/mysql-stability'
* hotfix/mysql-stability:
  Finer error checks
  Better test display
  Better testing output
  Wait 90 sec before using docker containers
  Better wait command
  Disable mysql socket
2016-12-30 18:37:34 +01:00
7f96c2b0ab Finer error checks 2016-12-28 17:00:21 +01:00
5719a9ec36 Better test display 2016-12-28 16:50:22 +01:00
a1df846526 Better testing output 2016-12-28 16:39:19 +01:00
d27f988107 Wait 90 sec before using docker containers 2016-12-28 16:03:52 +01:00
46c32c1e4c Better wait command 2016-12-27 17:13:27 +01:00
46202ca6dd Disable mysql socket 2016-12-27 16:49:47 +01:00
a0b3f8bfa2 Wait 40sec for containers to come up 2016-12-26 23:13:05 +01:00
3f689ebc75 Test each server version separately 2016-12-26 23:03:46 +01:00
f1097a3c68 Fix param check 2016-12-26 22:17:31 +01:00
28041d72bb Fix startup 2016-12-26 22:14:53 +01:00
3c3ecc5e4c Fix typos 2016-12-26 22:10:00 +01:00
f176f5a134 Split all into single builds 2016-12-26 22:03:21 +01:00
c3a38d3d5f Be more verbose 2016-12-26 21:50:50 +01:00
1502609913 Split builds 2016-12-26 21:44:04 +01:00
376576e495 Add multiple Linux dists 2016-12-26 15:51:27 +01:00
4edf7e24ff Clean .travis file 2016-12-26 15:45:05 +01:00
de3d89a631 Test Linux only 2016-12-26 15:32:35 +01:00
4d2d0eb63e Test Linux only 2016-12-26 15:31:30 +01:00
efe1e7b926 Add 2 OSX versions 2016-12-26 15:21:38 +01:00
bfa7bd4635 Make tests on Linux and OSX 2016-12-26 15:13:46 +01:00
acebbfbc16 Expect 4 OKs 2016-12-26 04:30:12 +01:00
ec860084c5 Fix travis version check 2016-12-26 03:54:59 +01:00
21da3a57ce Test MySQL 2016-12-26 03:35:09 +01:00
5520cade70 Test all PHP versions 2016-12-25 16:30:18 +01:00
95d0f34249 Better headlines 2016-12-25 15:46:02 +01:00
8c5274657b Enable correct version 2016-12-25 15:35:30 +01:00
ee270d70c2 Show sed commands 2016-12-25 15:30:33 +01:00
ea960268e2 Test enabled versions 2016-12-25 15:16:11 +01:00
133680c19c Fix travis sudo rights 2016-12-25 14:58:55 +01:00
a161e536a7 Add extensive travis checks 2016-12-22 20:17:35 +01:00
442a098690 Make host ports configurable via .env file 2016-12-22 20:16:39 +01:00
58cacbe23e Note about git tags and master branch 2016-12-21 15:16:10 +01:00
f829a2ed9d Preparing docker on OSX for d4m-nfs to improve FS performance 2016-12-14 11:15:33 +01:00
2916e6620d Default to store data within this repo 2016-12-02 21:09:58 +01:00
575fa0bf9c #24 make docker-host listening IP configurable via .env 2016-12-02 21:08:27 +01:00
075924fd6f Make mounts read-only where appropriate 2016-12-02 11:19:33 +01:00
d6920f77d3 Fix URL paths in dropdown menu 2016-12-02 11:18:10 +01:00
31efa378a6 Create dirs 2016-11-15 21:42:51 +01:00
92dcc0cec6 Clean up travis file 2016-11-15 21:15:52 +01:00
5a3b90dadd Use diff mysql port 2016-11-15 21:14:47 +01:00
4f451a146a Dont kill pg 2016-11-15 21:06:46 +01:00
efbb7bdfaf Kill system postgresql 2016-11-15 21:02:03 +01:00
befc10bb4a Switch PG port 2016-11-15 21:01:06 +01:00
a6bcf0093d List processes 2016-11-15 20:51:56 +01:00
34652dc563 Restructure travis file 2016-11-15 20:45:57 +01:00
bd05fae22f Fix compose command 2016-11-15 20:42:41 +01:00
6edf4b8a39 Show what is new 2016-11-15 20:27:27 +01:00
f4603911e7 #21 Adding docker-compose up 2016-11-15 20:26:53 +01:00
f49f1a9b22 Integrate PostgreSQL 2016-11-15 19:52:39 +01:00
e3ea211423 Revert dns finder for Linux 2016-11-15 19:52:13 +01:00
8834828a95 Refactor web libraries 2016-11-15 19:39:34 +01:00
086fd5bc50 Restructure web pages 2016-11-15 19:39:11 +01:00
bcfb2f6352 Adding Adminer SQL Manager 2016-11-15 19:38:26 +01:00
cde45407a1 Attaching new release tags 2016-11-06 17:53:04 +01:00
d1c7c27a54 Adding project documentation 2016-11-06 17:49:48 +01:00
b85dda99d9 Bind PHP docker to hotfix release v0.8.1 2016-11-06 17:22:29 +01:00
1cce1c91c1 Use absolute paths to include files 2016-11-06 17:21:59 +01:00
4ba01ebaea If no errors are present, show OK screen 2016-11-06 17:21:26 +01:00
24d3b65ec1 Include files by absolute path 2016-11-06 17:20:51 +01:00
28ec8e7285 Fix deprecation warning for PHP >5.5 2016-11-06 17:20:15 +01:00
98346d6f10 #10 - Make TLD suffix more configurable 2016-11-06 13:57:05 +01:00
e0e9c695b5 How to checkout latest stable release 2016-11-06 13:38:52 +01:00
4c2d5bb480 Refactor PHP code for intranet 2016-11-06 13:36:07 +01:00
2a05d1a0a8 Allow emails to be sorted 2016-11-05 02:57:10 +01:00
10446 changed files with 1614515 additions and 530993 deletions

View File

@ -1,3 +0,0 @@
<?php
// Fix DocumentRoot for VirtualDocumentRoot Hosts
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

View File

@ -1,30 +0,0 @@
#!/usr/bin/env php
<?php
// TODO: logpath could also be passed via CMD argument
// so this script could be more general
$path = '/var/log/apache-2.2';
$fh_timeout = 30; // 30 sek.
$fd = fopen('php://stdin', 'r');
while (!feof($fd)) {
$row = fgets($fd);
list($vhost, $h, $l, $u, $t, $r, $s, $b, $referrer, $ua) = explode(';', $row, 10);
if (!isset(${$vhost})) {
${$vhost} = fopen($path . '/' . $vhost . '_access.log', 'a+');
}
$lastwrite[$vhost] = time();
fputs(${$vhost}, "$h $l $u $t $r $s $b $referrer $ua");
foreach ($lastwrite as $vhost => $time) {
if ((time() - ($time + 30)) >= 0) {
fclose(${$vhost});
unset(${$vhost});
unset($lastwrite[$vhost]);
}
}
}

View File

@ -1,3 +0,0 @@
<?php
// Fix DocumentRoot for VirtualDocumentRoot Hosts
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

View File

@ -1,30 +0,0 @@
#!/usr/bin/env php
<?php
// TODO: logpath could also be passed via CMD argument
// so this script could be more general
$path = '/var/log/apache-2.4';
$fh_timeout = 30; // 30 sek.
$fd = fopen('php://stdin', 'r');
while (!feof($fd)) {
$row = fgets($fd);
list($vhost, $h, $l, $u, $t, $r, $s, $b, $referrer, $ua) = explode(';', $row, 10);
if (!isset(${$vhost})) {
${$vhost} = fopen($path . '/' . $vhost . '_access.log', 'a+');
}
$lastwrite[$vhost] = time();
fputs(${$vhost}, "$h $l $u $t $r $s $b $referrer $ua");
foreach ($lastwrite as $vhost => $time) {
if ((time() - ($time + 30)) >= 0) {
fclose(${$vhost});
unset(${$vhost});
unset($lastwrite[$vhost]);
}
}
}

4
.devilbox/cfg/mysql.cnf Normal file
View File

@ -0,0 +1,4 @@
[mysqld]
server_id = 1
log_bin = "mysql-bin"
sync_binlog = 0

View File

@ -1,23 +0,0 @@
CustomLog "/var/log/apache-2.2/access_log" combined
ErrorLog "/var/log/apache-2.2/error_log"
LogLevel warn
AddDefaultCharset UTF-8
# No DNS
HostnameLookups Off
#
Timeout 60
KeepAlive On
KeepAliveTimeout 10
MaxKeepAliveRequests 100
#
#
EnableMMAP Off
EnableSendfile Off
#
#
#
#
XSendFile On
XSendFilePath /shared/httpd

View File

@ -1,6 +0,0 @@
#### PHP-FPM config ####
AddType application/x-httpd-fastphp5 .php
Action application/x-httpd-fastphp5 /php5-fcgi
Alias /php5-fcgi /usr/local/bin/php-fcgi
FastCgiExternalServer /usr/local/bin/php-fcgi -host 172.16.238.11:9000 -pass-header Authorization

View File

@ -1,31 +0,0 @@
##
## Default Host for http://localhost
##
NameVirtualHost *:80
<VirtualHost _default_:80>
ServerName localhost
ServerAdmin root@localhost
ErrorLog /var/log/apache-2.2/localhost-error.log
CustomLog /var/log/apache-2.2/localhost-access.log combined
DirectoryIndex index.php index.html
DocumentRoot "/var/www/default/htdocs"
<Directory "/var/www/default/htdocs">
DirectoryIndex index.php index.html
AllowOverride All
Options All
RewriteEngine on
RewriteBase /
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

View File

@ -1,43 +0,0 @@
##
## Default Mass Virtual Host
##
<VirtualHost *:80>
# Get the server name from the Host: header
UseCanonicalName Off
ServerName localhost
ServerAlias *.loc
ServerAdmin root@localhost
# splitlogs.php is a custom script, which will filter the domain
# and create separate logfiles per domain.
LogFormat "%V;%h;%l;%u;%t;\"%r\";%>s;%b;\"%{Referer}i\";\"%{User-agent}i\"" vcommon
CustomLog "|/opt/bin/splitlogs.php" vcommon
ErrorLog /var/log/apache-2.2/other-error.log
DirectoryIndex index.php index.html
# When using VirtualDocumentRoot the PHP Env var DOCUMENT_ROOT
# is not filled, so we need to do that manually with a custom script.
VirtualDocumentRoot /shared/httpd/%-2+/htdocs/
php_admin_value auto_prepend_file /opt/bin/fix-virtual-docroot.php
<Directory "/shared/httpd/*/htdocs/">
DirectoryIndex index.php index.html
AllowOverride All
Options All
RewriteEngine on
RewriteBase /
Order allow,deny
Allow from all
</Directory>
</VirtualHost>

View File

@ -1,23 +0,0 @@
CustomLog "/var/log/apache-2.4/access_log" combined
ErrorLog "/var/log/apache-2.4/error_log"
LogLevel warn
AddDefaultCharset UTF-8
# No DNS
HostnameLookups Off
#
Timeout 60
KeepAlive On
KeepAliveTimeout 10
MaxKeepAliveRequests 100
#
#
EnableMMAP Off
EnableSendfile Off
#
#
#
#
XSendFile On
XSendFilePath /shared/httpd

View File

@ -1,17 +0,0 @@
#### PHP-FPM config ####
# enablereuse
# Defining a worker will improve performance
# And in this case, re-use the worker (dependent on support from the fcgi application)
# If you have enough idle workers, this would only improve the performance marginally
#
# enablereuse requires Apache 2.4.11 or later
#<Proxy "fcgi://172.16.238.11:9000/" enablereuse=on max=10></Proxy>
<FilesMatch "\.php$">
Require all granted
# Pick one of the following approaches
# Use the standard TCP socket
SetHandler "proxy:fcgi://172.16.238.11:9000"
# If your version of httpd is 2.4.9 or newer (or has the back-ported feature), you can use the unix domain socket
#SetHandler "proxy:unix:/path/to/app.sock|fcgi://localhost/:9000"
</FilesMatch>

View File

@ -1,32 +0,0 @@
##
## Default Host for http://localhost
##
<VirtualHost _default_:80>
ServerName localhost
ServerAdmin root@localhost
ErrorLog /var/log/apache-2.4/localhost-error.log
CustomLog /var/log/apache-2.4/localhost-access.log combined
DirectoryIndex index.php index.html
DocumentRoot "/var/www/default/htdocs"
<Directory "/var/www/default/htdocs">
DirectoryIndex index.php index.html
AllowOverride All
Options All
RewriteEngine on
RewriteBase /
Order allow,deny
Allow from all
Require all granted
</Directory>
</VirtualHost>

View File

@ -1,44 +0,0 @@
##
## Default Mass Virtual Host
##
<VirtualHost *:80>
# Get the server name from the Host: header
UseCanonicalName Off
ServerName localhost
ServerAlias *.loc
ServerAdmin root@localhost
# splitlogs.php is a custom script, which will filter the domain
# and create separate logfiles per domain.
LogFormat "%V;%h;%l;%u;%t;\"%r\";%>s;%b;\"%{Referer}i\";\"%{User-agent}i\"" vcommon
CustomLog "|/opt/bin/splitlogs.php" vcommon
ErrorLog /var/log/apache-2.4/other-error.log
DirectoryIndex index.php index.html
# When using VirtualDocumentRoot the PHP Env var DOCUMENT_ROOT
# is not filled, so we need to do that manually with a custom script.
VirtualDocumentRoot /shared/httpd/%-2+/htdocs/
php_admin_value auto_prepend_file /opt/bin/fix-virtual-docroot.php
<Directory "/shared/httpd/*/htdocs/">
DirectoryIndex index.php index.html
AllowOverride All
Options All
RewriteEngine on
RewriteBase /
Order allow,deny
Allow from all
Require all granted
</Directory>
</VirtualHost>

View File

@ -1,11 +0,0 @@
access_log /var/log/nginx-mainline/access.log main;
error_log /var/log/nginx-mainline/error.log warn;
charset utf-8;
send_timeout 60;
keepalive_timeout 10;
sendfile on;
tcp_nopush on;
tcp_nodelay on;

View File

@ -1,56 +0,0 @@
##
## Default Host for http://localhost
##
server {
listen 80 default_server;
server_name _;
# Root directive
root /var/www/default/htdocs;
index index.php;
access_log /var/log/nginx-mainline/localhost-access.log main;
error_log /var/log/nginx-mainline/localhost-error.log warn;
# Front-controller pattern as recommended by the nginx docs
location / {
try_files $uri $uri/ /index.php;
}
# PHP FPM
location ~ \.php?$ {
# PHP.INI:
# ---------------------------
# // Find this:
# cgi.fix_pathinfo=1
# // Replace with:
# cgi.fix_pathinfo=0
try_files $uri = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info ^(.+\.php)(.*)$;
#### FPM Server
fastcgi_pass 172.16.238.11:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
location ~ /\.ht {
deny all;
}
# disallow access to git configs path
location ~ /\.git {
deny all;
}
}

View File

@ -1,56 +0,0 @@
##
## Default Mass Virtual Host
##
server {
listen 80;
server_name ~^(?<domain>.+)\.loc$;
# Root directive
root /shared/httpd/$domain/htdocs/;
index index.php;
access_log /var/log/nginx-mainline/$domain-access.log main;
error_log /var/log/nginx-mainline/other-error.log warn;
# Front-controller pattern as recommended by the nginx docs
location / {
try_files $uri $uri/ /index.php;
}
# PHP FPM
location ~ \.php?$ {
# PHP.INI:
# ---------------------------
# // Find this:
# cgi.fix_pathinfo=1
# // Replace with:
# cgi.fix_pathinfo=0
try_files $uri = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info ^(.+\.php)(.*)$;
#### SOCKET
fastcgi_pass 172.16.238.11:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
location ~ /\.ht {
deny all;
}
# disallow access to git configs path
location ~ /\.git {
deny all;
}
}

View File

@ -1,11 +0,0 @@
access_log /var/log/nginx-stable/access.log main;
error_log /var/log/nginx-stable/error.log warn;
charset utf-8;
send_timeout 60;
keepalive_timeout 10;
sendfile on;
tcp_nopush on;
tcp_nodelay on;

View File

@ -1,56 +0,0 @@
##
## Default Host for http://localhost
##
server {
listen 80 default_server;
server_name _;
# Root directive
root /var/www/default/htdocs;
index index.php;
access_log /var/log/nginx-stable/localhost-access.log main;
error_log /var/log/nginx-stable/localhost-error.log warn;
# Front-controller pattern as recommended by the nginx docs
location / {
try_files $uri $uri/ /index.php;
}
# PHP FPM
location ~ \.php?$ {
# PHP.INI:
# ---------------------------
# // Find this:
# cgi.fix_pathinfo=1
# // Replace with:
# cgi.fix_pathinfo=0
try_files $uri = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info ^(.+\.php)(.*)$;
#### FPM Server
fastcgi_pass 172.16.238.11:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
location ~ /\.ht {
deny all;
}
# disallow access to git configs path
location ~ /\.git {
deny all;
}
}

View File

@ -1,56 +0,0 @@
##
## Default Mass Virtual Host
##
server {
listen 80;
server_name ~^(?<domain>.+)\.loc$;
# Root directive
root /shared/httpd/$domain/htdocs/;
index index.php;
access_log /var/log/nginx-stable/$domain-access.log main;
error_log /var/log/nginx-stable/other-error.log warn;
# Front-controller pattern as recommended by the nginx docs
location / {
try_files $uri $uri/ /index.php;
}
# PHP FPM
location ~ \.php?$ {
# PHP.INI:
# ---------------------------
# // Find this:
# cgi.fix_pathinfo=1
# // Replace with:
# cgi.fix_pathinfo=0
try_files $uri = 404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info ^(.+\.php)(.*)$;
#### SOCKET
fastcgi_pass 172.16.238.11:9000;
fastcgi_index index.php;
fastcgi_intercept_errors on;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
location ~ /\.ht {
deny all;
}
# disallow access to git configs path
location ~ /\.git {
deny all;
}
}

View File

@ -0,0 +1 @@
{"success":"true"}

View File

@ -1,43 +1,183 @@
<?PHP
// Measure time
$TIME_START = microtime(true);
$MY_DIR = dirname(__FILE__);
// Start session
session_start();
// Turn on all PHP errors
error_reporting(-1);
// Translate Docker environmental variables to $ENV
$ENV = array();
exec('env', $output);
foreach ($output as $var) {
$tmp = explode('=', $var);
$ENV[$tmp[0]] = $tmp[1];
}
// Shorten DNS timeouts for gethostbyname in case DNS server is down
putenv('RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1');
$DEVILBOX_VERSION = 'v1.11.0';
$DEVILBOX_DATE = '2022-03-22';
$DEVILBOX_API_PAGE = 'devilbox-api/status.json';
//
// Set Directories
//
$CONF_DIR = dirname(__FILE__);
$LIB_DIR = $CONF_DIR . DIRECTORY_SEPARATOR . 'include' . DIRECTORY_SEPARATOR .'lib';
$VEN_DIR = $CONF_DIR . DIRECTORY_SEPARATOR . 'include' . DIRECTORY_SEPARATOR .'vendor';
$LOG_DIR = dirname(dirname($CONF_DIR)) . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR . 'devilbox';
//
// Load Base classes
//
require $LIB_DIR . DIRECTORY_SEPARATOR . 'container' . DIRECTORY_SEPARATOR .'BaseClass.php';
require $LIB_DIR . DIRECTORY_SEPARATOR . 'container' . DIRECTORY_SEPARATOR .'BaseInterface.php';
// HTTPD Docker
//
// Set Docker addresses
//
$DNS_HOST_NAME = 'bind';
$PHP_HOST_NAME = 'php';
$HTTPD_HOST_NAME = 'httpd';
$HTTPD_HOST_ADDR = gethostbyname($HTTPD_HOST_NAME);
// PHP Docker
$PHP_HOST_NAME = 'php';
$PHP_HOST_ADDR = gethostbyname($PHP_HOST_NAME);
// MySQL Docker
$MYSQL_HOST_NAME = 'db';
$MYSQL_HOST_ADDR = gethostbyname($MYSQL_HOST_NAME);
$MYSQL_ROOT_PASS = $ENV['MYSQL_ROOT_PASSWORD'];
// MySQL Connection variables
$MY_MYSQL_ERR = NULL;
$MY_MYSQL_LINK = NULL;
// VirtualHost DNS check
// Temporarily disable due to:
// https://github.com/cytopia/devilbox/issues/8
$ENABLE_VHOST_DNS_CHECK = FALSE;
$MYSQL_HOST_NAME = 'mysql';
$PGSQL_HOST_NAME = 'pgsql';
$REDIS_HOST_NAME = 'redis';
$MEMCD_HOST_NAME = 'memcd';
$MONGO_HOST_NAME = 'mongo';
require $MY_DIR . DIRECTORY_SEPARATOR . 'include' . DIRECTORY_SEPARATOR .'functions.php';
//
// Lazy Container Loader
//
function loadFile($class, $base_path) {
static $_LOADED_FILE;
if (isset($CONNECT) && $CONNECT) {
$MY_MYSQL_LINK = my_mysql_connect($MY_MYSQL_ERR);
}
if (isset($_LOADED_FILE[$class])) {
return;
}
require $base_path . DIRECTORY_SEPARATOR . $class . '.php';
$_LOADED_FILE[$class] = true;
return;
}
function loadClass($class) {
static $_LOADED_LIBS;
if (isset($_LOADED_LIBS[$class])) {
return $_LOADED_LIBS[$class];
} else {
$lib_dir = $GLOBALS['LIB_DIR'];
$cnt_dir = $GLOBALS['LIB_DIR'] . DIRECTORY_SEPARATOR . 'container';
switch($class) {
//
// Lib Classes
//
case 'Logger':
loadFile($class, $lib_dir);
$_LOADED_LIBS[$class] = \devilbox\Logger::getInstance();
break;
case 'Html':
loadFile($class, $lib_dir);
$_LOADED_LIBS[$class] = \devilbox\Html::getInstance();
break;
case 'Helper':
loadFile($class, $lib_dir);
$_LOADED_LIBS[$class] = \devilbox\Helper::getInstance();
break;
//
// Docker Container Classes
//
case 'Php':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Php::getInstance($GLOBALS['PHP_HOST_NAME']);
break;
case 'Dns':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Dns::getInstance($GLOBALS['DNS_HOST_NAME']);
break;
case 'Httpd':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Httpd::getInstance($GLOBALS['HTTPD_HOST_NAME']);
break;
case 'Mysql':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Mysql::getInstance($GLOBALS['MYSQL_HOST_NAME'], array(
'user' => 'root',
'pass' => loadClass('Helper')->getEnv('MYSQL_ROOT_PASSWORD')
));
break;
case 'Pgsql':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Pgsql::getInstance($GLOBALS['PGSQL_HOST_NAME'], array(
'user' => loadClass('Helper')->getEnv('PGSQL_ROOT_USER'),
'pass' => loadClass('Helper')->getEnv('PGSQL_ROOT_PASSWORD'),
'db' => 'postgres'
));
break;
case 'Redis':
// Check if redis is using a password
$REDIS_ROOT_PASSWORD = '';
$_REDIS_ARGS = loadClass('Helper')->getEnv('REDIS_ARGS');
/*
* This pattern will match optional quoted string, 'my password' or "my password"
* or if there aren't any quotes, it will match up until the next space.
*/
$_REDIS_PASS = array();
preg_match_all('/--requirepass\s+("|\')?(?(1)(.*)|([^\s]*))(?(1)\1|)/', $_REDIS_ARGS, $_REDIS_PASS, PREG_SET_ORDER);
if (! empty($_REDIS_PASS)) {
/*
* In case the option is specified multiple times, use the last effective one.
*
* preg_match_all returns a multi-dimensional array, the first level array is in order of which was matched first,
* and the password string is either matched in group 2 or group 3 which is always the end of the sub-array.
*/
$_REDIS_PASS = end(end($_REDIS_PASS));
if (strlen($_REDIS_PASS) > 0) {
$REDIS_ROOT_PASSWORD = $_REDIS_PASS;
}
}
loadFile($class, $cnt_dir);
if ($REDIS_ROOT_PASSWORD == '') {
$_LOADED_LIBS[$class] = \devilbox\Redis::getInstance($GLOBALS['REDIS_HOST_NAME']);
} else {
$_LOADED_LIBS[$class] = \devilbox\Redis::getInstance($GLOBALS['REDIS_HOST_NAME'], array(
'pass' => $REDIS_ROOT_PASSWORD,
));
}
break;
case 'Memcd':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Memcd::getInstance($GLOBALS['MEMCD_HOST_NAME']);
break;
case 'Mongo':
loadFile($class, $cnt_dir);
$_LOADED_LIBS[$class] = \devilbox\Mongo::getInstance($GLOBALS['MONGO_HOST_NAME']);
break;
// Get optional docker classes
default:
// Unknown class
exit('Class does not exist: '.$class);
}
return $_LOADED_LIBS[$class];
}
}

View File

@ -0,0 +1,123 @@
<?php
require '../config.php';
if (loadClass('Helper')->isLoggedIn()) {
//
// ?database=
//
if (isset($_GET['database'])) {
// &type=mysql
if (isset($_GET['type']) && $_GET['type'] == 'mysql') {
echo json_encode(array(
'size' => (string)loadClass('Mysql')->getDBSize($_GET['database']),
'table' => (string)loadClass('Mysql')->getTableCount($_GET['database'])
));
// &type=postgres
} else if (isset($_GET['type']) && $_GET['type'] == 'postgres') {
$schema = isset($_GET['schema']) ? $_GET['schema'] : '';
echo json_encode(array(
'size' => (string)loadClass('Pgsql')->getSchemaSize($_GET['database'], $schema),
'table' => (string)loadClass('Pgsql')->getTableCount($_GET['database'], $schema)
));
}
}
//
// ?vhost=
//
else if (isset($_GET['vhost'])) {
echo loadClass('Httpd')->checkVirtualHost($_GET['vhost']);
}
//
// ?software=
//
else if (isset($_GET['software'])) {
$no = '<span class="text-danger">not installed</span>';
$software = array();
if ($_GET['software'] == 'composer') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getComposerVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'drupalc') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getDrupalConsoleVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'drush7') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getDrushVersion(7)) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'drush8') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getDrushVersion(8)) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'drush9') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getDrushVersion(9)) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'git') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getGitVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'laravel') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getLaravelVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'mds') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getMdsVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'node') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getNodeVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'npm') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getNpmVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'phalcon') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getPhalconVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'symfony') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getSymfonyVersion()) !== false) ? $version : $no
));
}
else if ($_GET['software'] == 'wpcli') {
echo json_encode(array(
$_GET['software'] => (($version = loadClass('Php')->getWpcliVersion()) !== false) ? $version : $no
));
} else {
echo json_encode(array($_GET['software'] => 'unknown software'));
}
}
//
// WRONG REQUEST
//
else {
loadClass('Helper')->redirect('/');
}
}
//
// Not logged in
//
else {
loadClass('Helper')->redirect('/');
}

View File

@ -1,11 +0,0 @@
<?php
$CONNECT = TRUE;
require '../config.php';
if (isset($_GET['size'])) {
echo getDBSize($_GET['size']);
} elseif (isset($_GET['table'])) {
echo getTableCount($_GET['table']);
} else {
echo '0';
}

View File

@ -1,8 +0,0 @@
<?php
require '../config.php';
if (isset($_GET['valid'])) {
echo checkVirtualHost($_GET['valid']);
} else {
echo '';
}

View File

@ -1,11 +1,64 @@
.meter {
height: 20px; /* Can be anything */
position: relative;
background: #555;
-moz-border-radius: 25px;
-webkit-border-radius: 25px;
border-radius: 25px;
box-shadow: inset 0 -1px 1px rgba(255,255,255,0.3);
}
.meter > span {
display: block;
height: 100%;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
background-color: rgb(43,194,83);
background-image: linear-gradient(
center bottom,
rgb(43,194,83) 37%,
rgb(84,240,84) 69%
);
box-shadow:
inset 0 2px 9px rgba(255,255,255,0.3),
inset 0 -2px 6px rgba(0,0,0,0.4);
position: relative;
overflow: hidden;
}
.dash-box {
border: 1px solid #383737;
background-color: #3d3d3d;
color: #999999;
height:100%;
}
.dash-box-head {
background-color: #383737;
color: #999999;
width:100%;
display: inline-block;
padding:10px;
font-weight: bold;
}
.dash-box-body {
padding:10px;
}
.row-margin {
margin-bottom:20px;
}
.col-margin {
margin-bottom:20px;
}
/* Bootstrap overwrites
-------------------------------------------------- */
html, body {
font-size: 14px;
}
td {
word-break: break-word;
font-size: 14px;
}
@ -18,7 +71,7 @@ html {
}
body {
/* Margin bottom by footer height */
margin-bottom: 80px;
margin-bottom: 80px !important;
}
.footer {
position: absolute;
@ -30,57 +83,64 @@ body {
}
/* Generics
-------------------------------------------------- */
.font-small {
font-size: 12px;
}
/* Circle Box
-------------------------------------------------- */
.circles{
margin:0px auto;
margin:0px auto;
}
.circles > div {
overflow:hidden;
float:left;
width:auto;
height:auto;
position: relative;
border-radius:50%;
-moz-border-radius:50%;
-webkit-border-radius:50%;
-khtml-border-radius: 50%;
background:#eee;
overflow:hidden;
float:left;
width:auto;
height:auto;
position: relative;
border-radius:50%;
-moz-border-radius:50%;
-webkit-border-radius:50%;
-khtml-border-radius: 50%;
background:#eee;
}
.circles > div > div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.circles > div > div > div {
display: table;
width: 100%;
height: 100%;
display: table;
width: 100%;
height: 100%;
}
.circles > div > div > div > div {
display: table-cell;
text-align: center;
vertical-align: middle;
display: table-cell;
text-align: center;
vertical-align: middle;
}
@media (max-width: 320px)
{
.circles > div {padding: 50%;}
.circles > div {padding: 50%;}
}
@media (min-width: 321px) and (max-width: 800px)
{
.circles > div {padding: 50%;}
.circles > div {padding: 50%;}
}
@media (min-width: 801px)
{
.circles > div {padding: 40%;}
.circles > div {padding: 48%;}
}
@ -90,25 +150,85 @@ body {
a.navbar-brand {
background-color: transparent !important;
}
a.navbar-brand img {
margin-right: 10px;
}
a.nav-link {
background-color: transparent !important;
background-color: transparent !important;
}
img.d-inline-block {
float: none;
float: none;
}
nav.navbar {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
font-size: 1rem;
line-height: 1.5;
color: #373a3c;
background-color: #fff;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
font-size: 1rem;
line-height: 1.5;
color: #373a3c;
background-color: #fff;
}
/* mailphp;
/* mail.php;
-------------------------------------------------- */
tr.subject {
cursor: pointer;
}
cursor: pointer;
}
td.break-word {
word-break: break-word;
}
/* adminer.php;
-------------------------------------------------- */
#menu {
position: absolute;
margin: 76px 0 0 !important;
}
#breadcrumb {
top: 60px !important;
}
#lang {
top: 53px !important;
}
.pages {
z-index:1000;
}
/* login.php;
-------------------------------------------------- */
/* Extra markup and styles for table-esque vertical and horizontal centering */
.site-wrapper {
display: table;
width: 100%;
height: 100%; /* For at least Firefox */
min-height: 100%;
-webkit-box-shadow: inset 0 0 5rem rgba(0,0,0,.5);
box-shadow: inset 0 0 5rem rgba(0,0,0,.5);
}
.site-wrapper-inner {
display: table-cell;
vertical-align: top;
}
.cover-container {
margin-right: auto;
margin-left: auto;
}
/* Affix and center */
@media (min-width: 40em) {
/* Start the vertical centering */
.site-wrapper-inner {
vertical-align: middle;
}
}
@media (min-width: 62em) {
.masthead,
.mastfoot,
.cover-container {
width: 32rem;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,22 @@
class HtmlEmail extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
let emailContent;
const templateId = this.dataset.templateId;
try {
emailContent = document.getElementById(templateId).innerHTML;
} catch (error) {
console.log(error);
return;
}
const container = document.createElement('div');
container.innerHTML = emailContent;
this.shadowRoot.appendChild(container);
}
}
customElements.define('html-email', HtmlEmail);

View File

@ -0,0 +1,62 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Httpd custom configs</h1>
<br/>
<br/>
<p>Shows your currently custom configuration files applied to the Httpd container.</p>
<div class="row">
<div class="col-md-12">
<?php $vHosts = loadClass('Httpd')->getVirtualHosts(); ?>
<?php $custom = false; ?>
<?php foreach ($vHosts as $vHost): ?>
<?php if (($vhostGen = loadClass('Httpd')->getVhostgenTemplatePath($vHost['name'])) !== false): ?>
<?php $custom = true; ?>
<?php endif; ?>
<?php endforeach; ?>
<?php if ($custom): ?>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Project</th>
<th>Host</th>
<th>Container</th>
<th>Files</th>
</tr>
</thead>
<tbody>
<?php foreach ($vHosts as $vHost): ?>
<?php if (($vhostGen = loadClass('Httpd')->getVhostgenTemplatePath($vHost['name'])) !== false): ?>
<tr>
<th><?php echo $vHost['domain']; ?></th>
<td><?php echo loadClass('Helper')->getEnv('HOST_PATH_HTTPD_DATADIR').'/'.$vHost['name'].'/'.loadClass('Helper')->getEnv('HTTPD_TEMPLATE_DIR');?></td>
<td><?php echo dirname($vhostGen); ?></td>
<td><code><?php echo basename($vhostGen); ?></code></td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
</tbody>
</table>
<?php else: ?>
<p>No custom configurations applied.</p>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,126 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>PHP custom configs</h1>
<br/>
<br/>
<p>Shows your currently custom configuration files applied to the PHP-FPM container.</p>
<div class="row">
<div class="col-md-12">
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Section</th>
<th>Host</th>
<th>Container</th>
<th>Files</th>
</tr>
</thead>
<tbody>
<tr>
<th>Supervisord</th>
<td>supervisor/</td>
<td>/etc/supervisor/custom.d/</td>
<td>
<?php
$files = glob('/etc/supervisor/custom.d/*.conf');
if ($files) {
foreach ($files as $file) {
echo '<code>'.basename($file). '</code><br/>';
}
} else {
echo 'No custom files';
}
?>
</td>
</tr>
<tr>
<th>Autostart (global)</th>
<td>autostart/</td>
<td>/startup.2.d/</td>
<td>
<?php
$files = glob('/startup.2.d/*.sh');
if ($files) {
foreach ($files as $file) {
echo '<code>'.basename($file). '</code><br/>';
}
} else {
echo 'No custom files';
}
?>
</td>
</tr>
<tr>
<th>Autostart (version)</th>
<td>cfg/php-startup-<?php echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;?>/</td>
<td>/startup.1.d/</td>
<td>
<?php
$files = glob('/startup.1.d/*.sh');
if ($files) {
foreach ($files as $file) {
echo '<code>'.basename($file). '</code><br/>';
}
} else {
echo 'No custom files';
}
?>
</td>
</tr>
<tr>
<th>PHP-FPM</th>
<td>cfg/php-fpm-<?php echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;?>/</td>
<td>/etc/php-fpm-custom.d/</td>
<td>
<?php
$files = glob('/etc/php-fpm-custom.d/*.conf');
if ($files) {
foreach ($files as $file) {
echo '<code>'.basename($file). '</code><br/>';
}
} else {
echo 'No custom files';
}
?>
</td>
</tr>
<tr>
<th>PHP</th>
<td>cfg/php-ini-<?php echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;?>/</td>
<td>/etc/php-custom.d/</td>
<td>
<?php
$files = glob('/etc/php-custom.d/*.ini');
if ($files) {
foreach ($files as $file) {
echo '<code>'.basename($file). '</code><br/>';
}
} else {
echo 'No custom files';
}
?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -1,12 +1,13 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php $FONT_AWESOME = TRUE; require '../include/head.php'; ?>
<?php echo loadClass('Html')->getHead(true); ?>
</head>
<body>
<?php require '../include/navigation.php'; ?>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
@ -18,7 +19,7 @@
<div class="col-md-6">
<h2>Contributors</h2>
<p>The following people have contributed to the <a href="https://github.com/cytopia/devilbox">Devilbox</a>.</p>
<p>The following people have contributed to the <a href="https://github.com/cytopia/devilbox/graphs/contributors">Devilbox</a>.</p>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
@ -56,30 +57,50 @@
</tr>
</thead>
<tbody>
<tr>
<td>Adminer</td>
<td>Apache License 2.0 or GPL 2</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/vrana/adminer">vrana/adminer</a></td>
</tr>
<tr>
<td>Bootstrap</td>
<td>MIT</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a href="https://github.com/twbs/bootstrap">twbs/bootstrap</a></td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/twbs/bootstrap">twbs/bootstrap</a></td>
</tr>
<tr>
<td>Font Awesome (css)</td>
<td>MIT</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a href="https://github.com/FortAwesome/Font-Awesome">FortAwesome/Font-Awesome</a></td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/FortAwesome/Font-Awesome">FortAwesome/Font-Awesome</a></td>
</tr>
<tr>
<td>Font Awesome (fonts)</td>
<td>SIL OFL 1.1</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a href="https://github.com/FortAwesome/Font-Awesome">FortAwesome/Font-Awesome</a></td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/FortAwesome/Font-Awesome">FortAwesome/Font-Awesome</a></td>
</tr>
<tr>
<td>Opcache GUI</td>
<td>MIT</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a href="https://github.com/amnuts/opcache-gui">amnuts/opcache-gui</a></td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/amnuts/opcache-gui">amnuts/opcache-gui</a></td>
</tr>
<tr>
<td>PHPMemcachedAdmin</td>
<td>Apache 2.0</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/elijaa/phpmemcachedadmin">elijaa/phpmemcachedadmin</a></td>
</tr>
<tr>
<td>phpMyAdmin</td>
<td>GPL 2.0</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a href="https://github.com/phpmyadmin/phpmyadmin">phpmyadmin/phpmyadmin</a></td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/phpmyadmin/phpmyadmin">phpmyadmin/phpmyadmin</a></td>
</tr>
<tr>
<td>phpPgAdmin</td>
<td>GPL 2.0</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/phppgadmin/phppgadmin">phppgadmin/phppgadmin</a></td>
</tr>
<tr>
<td>PHPRedMin</td>
<td>BSD 3-Clause License</td>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/sasanrose/phpredmin">sasanrose/phpredmin</a></td>
</tr>
</tbody>
</table>
@ -87,11 +108,8 @@
</div>
</div><!-- /.container -->
<?php require '../include/footer.php'; ?>
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -1,116 +0,0 @@
<?php $CONNECT = TRUE; require '../config.php'; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php require '../include/head.php'; ?>
</head>
<body>
<?php require '../include/navigation.php'; ?>
<div class="container">
<h1>Databases</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Name</th>
<th>Charset</th>
<th>Collation</th>
<th>Tables</th>
<th>Size</th>
</th>
</thead>
<tbody>
<?php foreach (getDatabases() as $name => $keys): ?>
<tr>
<td><?php echo $name;?></td>
<td><?php echo $keys['charset'];?></td>
<td><?php echo $keys['collation'];?></td>
<td><code><span class="table" id="table-<?php echo $name;?>">&nbsp;&nbsp;&nbsp;&nbsp;</span></code></td>
<td><code><span class="size" id="size-<?php echo $name;?>">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></code></td>
</tr>
<input type="hidden" name="database[]" class="database" value="<?php echo $name;?>" />
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div><!-- /.container -->
<?php require '../include/footer.php'; ?>
<script>
// self executing function here
(function() {
// your page initialization code here
// the DOM will be available here
function updateSizes(database) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var fill = '';
var res = '';
var len;
var i;
if (this.readyState == 4 && this.status == 200) {
res = (this.responseText) == 0 ? '0sss MB' : this.responseText+' MB';
len = res.length;
if (len < 9) {
for (i=len; i<9; i++) {
fill = '&nbsp;' + fill;
}
}
res = res.replace('sss', '&nbsp;&nbsp;&nbsp;');
res = fill + res;
document.getElementById('size-' + database).innerHTML = res;
}
};
xhttp.open('GET', '_ajax_db.php?size=' + database, true);
xhttp.send();
}
function updateCount(database) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var fill = '';
var i;
if (this.readyState == 4 && this.status == 200) {
if (this.responseText.length < 4) {
for (i=this.responseText.length; i<4; i++) {
fill = '&nbsp;' + fill;
}
}
document.getElementById('table-' + database).innerHTML = fill + this.responseText;
}
};
xhttp.open('GET', '_ajax_db.php?table=' + database, true);
xhttp.send();
}
var databases = document.getElementsByName('database[]');
var database;
for (i = 0; i < databases.length; i++) {
database = databases[i].value;
updateSizes(database);
updateCount(database);
}
})();
</script>
</body>
</html>

View File

@ -0,0 +1,53 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Memcached Keys</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Memcd')->isAvailable()): ?>
<p>Memcached container is not running.</p>
<?php else: ?>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Key</th>
<th>Size</th>
<th>TTL</th>
<th>Value</th>
</th>
</thead>
<tbody>
<?php foreach (loadClass('Memcd')->getKeys() as $data): ?>
<tr>
<td><?php print_r($data['key']);?></td>
<td><?php print_r($data['size']);?></td>
<td><?php print_r($data['ttl']);?></td>
<td><?php print_r($data['val']);?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,51 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>MongoDB Databases</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Mongo')->isAvailable()): ?>
<p>MongoDB container is not running.</p>
<?php else: ?>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Name</th>
<th>Size</th>
<th>Empty</th>
</th>
</thead>
<tbody>
<?php foreach (loadClass('Mongo')->getDatabases() as $db): ?>
<tr>
<td><?php echo $db['name'];?></td>
<td><?php echo round($db['size']/(1024*1024), 2);?> MB</td>
<td><?php echo $db['empty'];?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,114 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
// Also required for JS calls (see bottom of this page)
$len_table = 4;
$len_size = 9;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>MySQL Databases</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Mysql')->isAvailable()): ?>
<p>MySQL container is not running.</p>
<?php else: ?>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Name</th>
<th>Charset</th>
<th>Collation</th>
<th>Tables</th>
<th>Size</th>
</th>
</thead>
<tbody>
<?php foreach (loadClass('Mysql')->getDatabases() as $name => $keys): ?>
<tr>
<td><?php echo $name;?></td>
<td><?php echo $keys['charset'];?></td>
<td><?php echo $keys['collation'];?></td>
<td><code><span class="table" id="table-<?php echo $name;?>"><?php echo str_repeat('&nbsp;', $len_table);?></span></code></td>
<td><code><span class="size" id="size-<?php echo $name;?>"><?php echo str_repeat('&nbsp;', $len_size);?></span></code></td>
</tr>
<input type="hidden" name="database[]" class="database" value="<?php echo $name;?>" />
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
<script>
// self executing function here
(function() {
// your page initialization code here
// the DOM will be available here
function updateData(database) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var res = null;
var size = 0;
var tables = 0;
var i;
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.response);
// Normalize size output
size = res.size == 0 ? '0sss MB' : res.size + ' MB';
if (size.length < <?php echo $len_size;?>) {
for (i = size.length; i < <?php echo $len_size;?>; ++i) {
size = '&nbsp;' + size;
}
}
size = size.replace('sss', '&nbsp;&nbsp;&nbsp;');
// Normalize tables output
tables = res.table;
if (tables.length < <?php echo $len_table;?>) {
for (i = tables.length; i < <?php echo $len_table;?>; ++i) {
tables = '&nbsp;' + tables;
}
}
document.getElementById('size-' + database).innerHTML = size;
document.getElementById('table-' + database).innerHTML = tables;
}
};
xhttp.open('GET', '_ajax_callback.php?type=mysql&database=' + database, true);
xhttp.send();
}
var databases = document.getElementsByName('database[]');
var database;
for (i = 0; i < databases.length; i++) {
database = databases[i].value;
updateData(database);
}
})();
</script>
</body>
</html>

View File

@ -0,0 +1,126 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
// Also required for JS calls (see bottom of this page)
$len_table = 4;
$len_size = 9;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>PostgreSQL Databases</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Pgsql')->isAvailable()): ?>
<p>PgSQL container is not running.</p>
<?php else: ?>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Name</th>
<th>Charset</th>
<th>Collation</th>
<th>Tables</th>
<th>Size</th>
</th>
</thead>
<tbody>
<?php foreach (loadClass('Pgsql')->getDatabases() as $name => $database): ?>
<tr class="table-info">
<th>
<?php echo $name;?>
</th>
<td><?php echo $database['charset'];?></td>
<td><?php echo $database['collation'];?></td>
<td colspan="2"></td>
</tr>
<?php foreach ($database['schemas'] as $schema => $data): ?>
<tr>
<td><?php echo $schema;?></td>
<td colspan="2"></td>
<td><code><span class="table" id="table-<?php echo $name.'-'.$schema;?>"><?php echo str_repeat('&nbsp;', $len_table);?></span></code></td>
<td><code><span class="size" id="size-<?php echo $name.'-'.$schema;?>"><?php echo str_repeat('&nbsp;', $len_size);?></span></code></td>
</tr>
<input type="hidden" name="schema[]" data-database="<?php echo $name;?>" class="schema" value="<?php echo $schema;?>" />
<?php endforeach; ?>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
<script>
// self executing function here
(function() {
// your page initialization code here
// the DOM will be available here
function updateData(database, schema) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var res = null;
var size = 0;
var tables = 0;
var i;
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.response);
// Normalize size output
size = res.size == 0 ? '0sss MB' : res.size + ' MB';
if (size.length < <?php echo $len_size;?>) {
for (i = size.length; i < <?php echo $len_size;?>; ++i) {
size = '&nbsp;' + size;
}
}
size = size.replace('sss', '&nbsp;&nbsp;&nbsp;');
// Normalize tables output
tables = res.table;
if (tables.length < <?php echo $len_table;?>) {
for (i = tables.length; i < <?php echo $len_table;?>; ++i) {
tables = '&nbsp;' + tables;
}
}
document.getElementById('size-' + database + '-' + schema).innerHTML = size;
document.getElementById('table-' + database + '-' + schema).innerHTML = tables;
}
};
xhttp.open('GET', '_ajax_callback.php?type=postgres&database=' + database + '&schema=' + schema, true);
xhttp.send();
}
var schemas = document.getElementsByName('schema[]');
var schema;
var database;
for (i = 0; i < schemas.length; i++) {
schema = schemas[i].value;
database = schemas[i].getAttribute('data-database');
updateData(database, schema);
}
})();
</script>
</body>
</html>

View File

@ -0,0 +1,101 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
if (isset($_GET['redisdb'])) {
loadClass('Redis')->flushDB($_GET['redisdb']);
loadClass('Helper')->redirect('/db_redis.php');
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Redis Keys</h1>
<br/>
<br/>
<?php $databases = array_keys(loadClass('Redis')->getKeys()); ?>
<?php if (count($databases)): ?>
<div class="row">
<div class="col-md-12">
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="redisdb">Redis DB</label>
<select class="form-control" name="redisdb">
<option value="" selected disabled>Select Redis DB</option>
<?php foreach ($databases as $db): ?>
<option value="<?php echo $db;?>"><?php echo $db;?></option>
<?php endforeach; ?>
</select>
</div>&nbsp;&nbsp;
<button type="submit" class="btn btn-primary">Flush database</button>
</form>
<br/>
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Redis')->isAvailable()): ?>
<p>Redis container is not running.</p>
<?php else: ?>
<table class="table table-striped ">
<tbody>
<?php $redisKeys = loadClass('Redis')->getKeys(); ?>
<?php if (count($redisKeys)): ?>
<?php foreach ($redisKeys as $db_name => $keys): ?>
<tr class="thead-inverse ">
<th colspan="5">
Database: <?php echo $db_name; ?>&nbsp;&nbsp;&nbsp;&nbsp;
Items: <?php echo count($keys); ?>
</th>
</th>
<tr class="table-info">
<tr>
<th>DB</th>
<th>Key</th>
<th>Expires</th>
<th>Type</th>
<th>Value</th>
</th>
</tr>
<?php foreach ($keys as $key): ?>
<tr>
<td><?php echo $db_name;?></td>
<td class="break-word" style="width:30%;"><?php echo $key['name'];?></td>
<td><?php echo $key['ttl'];?>s</td>
<td><?php echo $key['type'];?></td>
<td class="break-word">
<code>
<?php echo htmlentities($key['val']);?>
</code>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
<?php else: ?>
<p>No keys set.</p>
<?php endif; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,68 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Devilbox Debug</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php $errors = loadClass('Logger')->getAll(); ?>
<?php if ($errors === false): ?>
<p>Writing to logfile is not possible. Errors will be sent as mail instead. Check the mail section.</p>
<?php elseif (count($errors) === 0): ?>
<p>No errors detected.</div>
<?php else: ?>
<?php $total = count($errors); ?>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th>date</th>
<th>Errors (<?php echo $total;?>)</th>
</tr>
</thead>
<tbody>
<?php for ($i=($total-1); $i>=0; --$i): ?>
<tr>
<th><?php echo ($i+1);?></th>
<th><code><?php echo $errors[$i]['date'];?></code></th>
<th><code><?php echo $errors[$i]['head'];?></code></th>
<?php if (isset($errors[$i]['body'])): ?>
</tr>
<tr>
<td colspan="3">
<?php
$dump = implode('', $errors[$i]['body']);
//$dump = str_replace("=&gt;</font> \n", '=&gt;</font>', $dump);
?>
<code><?php echo $dump; ?></code>
</td>
</tr>
<?php endif; ?>
</tr>
<?php endfor; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Httpd info</h1>
<br/>
<br/>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<iframe style="width:100%; height:100vh; position:relative;" src="/devilbox-httpd-status" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,52 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Memcached Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Memcd')->isAvailable()): ?>
<p>Memcached container is not running.</p>
<?php else: ?>
<?php foreach (loadClass('Memcd')->getInfo() as $srv => $data): ?>
<h2><?php echo $srv; ?></h2>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach ($data as $key => $val): ?>
<tr>
<td><?php echo $key;?></td>
<td class="break-word"><code><?php echo $val;?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,49 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>MongoDB Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Mongo')->isAvailable()): ?>
<p>MongoDB container is not running.</p>
<?php else: ?>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach (loadClass('Mongo')->getInfo() as $key => $val): ?>
<tr>
<td><?php print_r($key);?></td>
<td class="break-word"><pre><?php print_r($val);?></pre></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,56 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>MySQL Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Mysql')->isAvailable()): ?>
<p>MySQL container is not running.</p>
<?php else: ?>
<p>For reference see here:</p>
<ul>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html</a></li>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html</a></li>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html</a></li>
</ul>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach (loadClass('Mysql')->getConfig() as $key => $val): ?>
<tr>
<td><?php echo $key;?></td>
<td class="break-word"><code><?php echo $val;?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,49 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>PostgreSQL Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Pgsql')->isAvailable()): ?>
<p>PgSQL container is not running.</p>
<?php else: ?>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach (loadClass('Pgsql')->getConfig() as $key => $val): ?>
<tr>
<td><?php echo $key;?></td>
<td class="break-word"><code><?php echo $val;?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,27 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<div class="row">
<div class="col-md-12">
<style>
/* prevent hhvm phpinfo() from shrinking the width */
body {width: 100% !important;}
</style>
<?php phpinfo(); ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,49 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Redis Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!loadClass('Redis')->isAvailable()): ?>
<p>Redis container is not running.</p>
<?php else: ?>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th>Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach (loadClass('Redis')->getInfo() as $key => $val): ?>
<tr>
<td><?php echo $key;?></td>
<td class="break-word"><code><?php echo $val;?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,66 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
if (!isset($_GET['name'])) {
loadClass('Helper')->redirect('/vhosts.php');
}
if (!strlen($_GET['name'])) {
loadClass('Helper')->redirect('/vhosts.php');
}
$vhost = $_GET['name'];
$found = false;
$vhosts = loadClass('Httpd')->getVirtualHosts();
foreach ($vhosts as $v) {
if ($vhost == $v['name']) {
$found = true;
break;
}
}
// Be safe before using outputs
$vhost = htmlentities($vhost);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(true); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>vhost-gen: <?php echo $vhost;?></h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<?php if (!$found): ?>
<p>The Virtual Host "<?php echo $vhost; ?>" does not exist.</p>
<?php else: ?>
<?php $tpl = loadClass('Httpd')->getVhostgenTemplatePath($vhost); ?>
<?php if (!$tpl): ?>
<p>No custom vhost-gen configuration found for "<?php echo $vhost; ?>".</p>
<?php else: ?>
<p>Note: If the resulting virtual host config does not reflect the vhost-gen template changes, you will need to restart the Devilbox.</p>
<a href="/vhosts.php"><i class="fa fa-chevron-left" aria-hidden="true"></i> Overview</a><br/>
<br/><h3>virtual host config</h3><br/>
<a title="Virtual host: <?php echo $vhost;?>.conf" target="_blank" href="/vhost.d/<?php echo $vhost;?>.conf">
<i class="fa fa-external-link" aria-hidden="true"></i> <?php echo $vhost;?>.conf
</a>
<br/><br/><h3>vhost-gen config</h3><br/>
<code><?php echo $tpl; ?></code><br/><br/>
<?php $lines = file($tpl); ?>
<pre style="border: 1px solid black; padding:5px;"><code><?php foreach ($lines as $line): ?><?php echo $line; ?><?php endforeach; ?></code></pre>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,32 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<div class="row">
<div class="col-md-12">
<style>
body {width: 100% !important;}
</style>
<?php if (($version = phpversion('xdebug')) === false): ?>
<p><code>xdebug</code> module is not enabled.</p>
<?php elseif (!function_exists('xdebug_info')): ?>
<p>Xdebug info only available with <code>xdebug 3.x.x</code> or greater. Your version is <code>xdebug <?php echo $version;?></code></p>
<?php else:?>
<?php xdebug_info(); ?>
<?php endif; ?>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

View File

@ -0,0 +1,66 @@
<?php require '../config.php'; ?>
<?php
// If login protection is disabled or user has already logged in
if (loadClass('Helper')->isloggedIn()) {
loadClass('Helper')->redirect('/');
}
// Validate $_POST login
$login_error = '';
if (isset($_POST['username']) && isset($_POST['password'])) {
// Auth successful
if (loadClass('Helper')->login($_POST['username'], $_POST['password'])) {
loadClass('Helper')->redirect('/');
}
$login_error = 'Wrong username or password';
}
?>
<!DOCTYPE html>
<html lang="en" style="height: 100%;min-height: 100%;">
<head>
<?php echo loadClass('Html')->getHead(true); ?>
</head>
<body style="height: 100%; min-height: 100%; text-align: center; color: #fff; text-shadow: 0 .05rem .1rem rgba(0,0,0,.5); background: #1f1f1f; margin-bottom:0 !important;">
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="container">
<div class="inner cover">
<img src="/assets/img/banner.png" style="width:60%; padding-bottom:20px;"/>
<h1 class="cover-heading">Devilbox Login</h1>
<div class="text-danger"><?php echo $login_error; ?></div>
<form method="POST">
<div class="form-group row">
<div class="col-sm-12">
<input type="text" class="form-control" id="inputUsername" placeholder="Username" name="username" value="<?php echo isset($_POST['username']) ? $_POST['username'] : ''; ?>">
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<input type="password" class="form-control" id="inputPassword" placeholder="Password" name="password">
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-primary">Sign in</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,11 @@
<?php require '../config.php'; ?>
<?php
if (isset($_GET['id'])) {
if ($_GET['id'] == session_id()) {
loadClass('Helper')->logout();
loadClass('Helper')->redirect('/login.php');
}
}
loadClass('Helper')->redirect('/');

View File

@ -1,39 +1,109 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
require '../config.php';
if (isset($_GET['email']) && isset($_GET['subject']) && isset($_GET['message'])) {
$mail = $_GET['email'];
$subj = $_GET['subject'];
$mess = $_GET['message'];
mail($mail, $subj, $mess);
//
// $_POST submit for sending a test email
//
if (isset($_POST['email']) && isset($_POST['subject']) && isset($_POST['message'])) {
$mail = $_POST['email'];
$subj = $_POST['subject'];
$mess = $_POST['message'];
if (! mail($mail, $subj, $mess)) {
loadClass('Logger')->error('Could not send mail to: '.$mail.' | subject: '.$subj);
}
header('Location: /mail.php');
exit();
}
//
// Includes
//
require $VEN_DIR . DIRECTORY_SEPARATOR . 'Mail' . DIRECTORY_SEPARATOR .'Mbox.php';
require $VEN_DIR . DIRECTORY_SEPARATOR . 'Mail' . DIRECTORY_SEPARATOR .'mimeDecode.php';
require $LIB_DIR . DIRECTORY_SEPARATOR . 'Mail.php';
require $LIB_DIR . DIRECTORY_SEPARATOR . 'Sort.php';
if (isset($_GET['delete']) && is_numeric($_GET['delete'])) {
$message = $_GET['delete'];
$MyMbox = new \devilbox\Mail('/var/mail/devilbox');
$MyMbox->delete($message);
header('Location: /mail.php');
exit();
}
//
// Setup Sort/Order
//
require '../include/vendor/Mail/Mbox.php';
require '../include/vendor/Mail/mimeDecode.php';
// Sort/Order settings
$defaultSort = array('sort' => 'date', 'order' => 'DESC');
$allowedSorts = array('date', 'subject', 'x-original-to', 'from');
$allowedOrders = array('ASC', 'DESC');
$GET_sortKeys = array('sort' => 'sort', 'order' => 'order');
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['crlf'] = "\r\n";
// Get sort/order
$MySort = new \devilbox\Sort($defaultSort, $allowedSorts, $allowedOrders, $GET_sortKeys);
$sort = $MySort->getSort();
$order = $MySort->getOrder();
$mbox = new Mail_Mbox('/var/mail/mailtrap');
// Evaluate Sorters/Orderers
$orderDate = '<a href="/mail.php?sort=date&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a>';
$orderFrom = '<a href="/mail.php?sort=from&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a>';
$orderTo = '<a href="/mail.php?sort=x-original-to&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a>';
$orderSubj = '<a href="/mail.php?sort=subject&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a>';
if ($sort == 'date') {
if ($order == 'ASC') {
$orderDate = '<a href="/mail.php?sort=date&order=DESC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-numeric-asc" aria-hidden="true"></i>';
} else {
$orderDate = '<a href="/mail.php?sort=date&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-numeric-desc" aria-hidden="true"></i> ';
}
} else if ($sort == 'subject') {
if ($order == 'ASC') {
$orderSubj = '<a href="/mail.php?sort=subject&order=DESC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-asc" aria-hidden="true"></i>';
} else {
$orderSubj = '<a href="/mail.php?sort=subject&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-desc" aria-hidden="true"></i>';
}
} else if ($sort == 'x-original-to') {
if ($order == 'ASC') {
$orderTo = '<a href="/mail.php?sort=x-original-to&order=DESC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-asc" aria-hidden="true"></i>';
} else {
$orderTo = '<a href="/mail.php?sort=x-original-to&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-desc" aria-hidden="true"></i>';
}
} else if ($sort == 'from') {
if ($order == 'ASC') {
$orderFrom = '<a href="/mail.php?sort=from&order=DESC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-asc" aria-hidden="true"></i>';
} else {
$orderFrom = '<a href="/mail.php?sort=from&order=ASC"><i class="fa fa-sort" aria-hidden="true"></i></a> <i class="fa fa-sort-alpha-desc" aria-hidden="true"></i>';
}
}
//
// Mbox Reader
//
$MyMbox = new \devilbox\Mail('/var/mail/devilbox');
// If default sort is on, use NULL, so we do not have to sort the mails after retrieval,
// because they are being read in the default sort/order anyway
$sortOrderArr = $MySort->isDefault($sort, $order) ? null : array($sort => $order);
$messages = $MyMbox->get($sortOrderArr);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php require '../include/head.php'; ?>
<?php echo loadClass('Html')->getHead(true); ?>
</head>
<body>
<?php require '../include/navigation.php'; ?>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Mail</h1>
<br/>
<br/>
@ -49,7 +119,7 @@ $mbox = new Mail_Mbox('/var/mail/mailtrap');
<div class="row">
<div class="col-md-12">
<form class="form-inline">
<form method="post" class="form-inline">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail1">Email to</label>
<input name="email" type="email" class="form-control" id="exampleInputEmail1" placeholder="Enter to email">
@ -62,7 +132,7 @@ $mbox = new Mail_Mbox('/var/mail/mailtrap');
<div class="form-group">
<label class="sr-only" for="exampleInputEmail3">Message</label>
<input name="message" type="text" class="form-control" id="exampleInputEmail3" placeholder="Message">
<textarea name="message" rows="1" class="form-control" id="exampleInputEmail3" placeholder="Message"></textarea>
</div>
<button type="submit" class="btn btn-primary">Send Email</button>
@ -82,63 +152,87 @@ $mbox = new Mail_Mbox('/var/mail/mailtrap');
</div>
<div class="row">
<div class="col-md-12">
<?php $mbox->open(); ?>
<table class="table table-striped table-hover">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th style="word-break: normal;">Date</th>
<th>To</th>
<th>Subject</th>
<th>Date <?php echo $orderDate;?></th>
<th>From <?php echo $orderFrom;?></th>
<th>To <?php echo $orderTo;?></th>
<th>Subject <?php echo $orderSubj;?></th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php for ($n = ($mbox->size()-1); $n >= 0; $n--): ?>
<?php foreach ($messages as $data): ?>
<?php
$message = $mbox->get($n);
$decode = new Mail_mimeDecode($message, "\r\n");
$structure = $decode->decode($params);
$message = htmlentities($data['raw']);
$structure = $data['decoded'];
$body = null;
if (isset($structure->body)) {
$body = $structure->body;
}
elseif(isset($structure->parts[1]->body)) {
$body = $structure->parts[1]->body;
}
elseif(isset($structure->parts[0]->body)) {
$body = $structure->parts[0]->body;
}
?>
<tr id="<?php echo $n;?>" class="subject">
<td><?php echo $n;?></td>
<tr id="<?php echo $data['num'];?>" class="subject">
<td><?php echo $data['num'];?></td>
<td>
<?php echo date('H:i', strtotime($structure->headers['date']));?><br/>
<small><?php echo date('Y-m-d', strtotime($structure->headers['date']));?></small>
</td>
<td><?php echo $structure->headers['x-original-to'];?></td>
<td><?php echo $structure->headers['subject'];?></td>
<td><?php echo htmlentities($structure->headers['from']);?></td>
<td><?php echo htmlentities($structure->headers['x-original-to']);?></td>
<td><?php echo htmlentities($structure->headers['subject']);?></td>
<td><a href="/mail.php?delete=<?php echo $data['num']-1;?>" title="Delete Email"><i class="fa fa-trash"></i></a></td>
</tr>
<tr></tr>
<tr id="mail-<?php echo $n;?>" style="display:none">
<tr id="mail-<?php echo $data['num'];?>" style="display:none">
<td></td>
<td colspan="3">
<pre><?php echo $message;?></pre>
<td colspan="5">
<?php if ($body !== null): ?>
<template id="mail-body-<?=$data['num']?>"><?=$body?></template>
<html-email data-template-id="mail-body-<?=$data['num']?>"></html-email>
<?php else: ?>
<div class="alert alert-warning" role="alert">
No valid body found
</div>
<?php endif; ?>
<hr>
<p><a class="btn btn-primary" data-toggle="collapse" href="#email-<?php echo $data['num'];?>" aria-expanded="false" aria-controls="email-<?php echo $data['num'];?>">Raw source</a></p>
<div class="collapse" id="email-<?php echo $data['num'];?>"><pre><?php echo $message;?></pre></div>
</td>
</tr>
<?php endfor; ?>
<?php endforeach; ?>
</tbody>
</table>
<?php $mbox->close(); ?>
</div>
</div>
</div><!-- /.container -->
<?php require '../include/footer.php'; ?>
<?php echo loadClass('Html')->getFooter(); ?>
<script>
$(function() {
$('.subject').each(function() {
$(this).click(function() {
var id = ($(this).attr('id'));
$('#mail-'+id).toggle();
})
$('.subject').click(function() {
var id = ($(this).attr('id'));
$('#mail-'+id).toggle();
})
// Handler for .ready() called.
});
</script>
<script src="/assets/js/html-email.js"></script>
</body>
</html>

View File

@ -1,51 +0,0 @@
<?php $CONNECT = TRUE; require '../config.php'; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php require '../include/head.php'; ?>
</head>
<body>
<?php require '../include/navigation.php'; ?>
<div class="container">
<h1>MySQL Info</h1>
<br/>
<br/>
<div class="row">
<div class="col-md-12">
<p>For reference see here:</p>
<ul>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html</a></li>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html</a></li>
<li><a target="_blank" href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html">https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html</a></li>
</ul>
<table class="table table-striped">
<thead class="thead-inverse">
<tr>
<th style="word-break: normal;">Variable</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<?php foreach (getMySQLConfig() as $key => $val): ?>
<tr>
<td style="word-break: normal;"><?php echo $key;?></td>
<td><?php echo $val;?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div><!-- /.container -->
<?php require '../include/footer.php'; ?>
</body>
</html>

View File

@ -1,4 +1,5 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<?php
/**
@ -12,6 +13,7 @@
* @license MIT, http://acollington.mit-license.org/
*/
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE);
/*
* User configuration
@ -53,13 +55,13 @@ class OpCacheService
'debounce_rate' => 250
];
private function __construct($options = [])
private function __construct($options = array())
{
$this->options = array_merge($this->defaults, $options);
$this->data = $this->compileState();
}
public static function init($options = [])
public static function init($options = array())
{
$self = new self($options);
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
@ -148,7 +150,7 @@ class OpCacheService
$status = opcache_get_status();
$config = opcache_get_configuration();
$files = [];
$files = array();
if (!empty($status['scripts']) && $this->getOption('allow_filelist')) {
uasort($status['scripts'], function($a, $b) {
return $a['hits'] < $b['hits'];
@ -190,7 +192,7 @@ class OpCacheService
]
);
$directives = [];
$directives = array();
ksort($config['directives']);
foreach ($config['directives'] as $k => $v) {
$directives[] = ['k' => $k, 'v' => $v];
@ -230,7 +232,7 @@ $opcache = OpCacheService::init($options);
<!doctype html>
<html>
<head>
<?php require '../include/head.php'; ?>
<?php echo loadClass('Html')->getHead(); /* devilbox edit */ ?>
<meta charset="UTF-8"/>
@ -238,7 +240,7 @@ $opcache = OpCacheService::init($options);
<title>OPcache statistics on <?php echo $opcache->getData('version', 'host'); ?></title>
<script src="/vendor/react/react.min.js"></script>
<script src="/vendor/react/react-dom.min.js"></script>
<script src="/vendor/jquery/jquery-2.2.3.min.js"></script>
<script src="/vendor/jquery/jquery-3.2.1.min.js"></script>
<style type="text/css">
body { font-family:sans-serif; font-size:90%; padding: 0; margin: 0 }
nav { padding-top: 20px; }
@ -321,7 +323,7 @@ $opcache = OpCacheService::init($options);
</head>
<body>
<?php require '../include/navigation.php'; ?>
<?php echo loadClass('Html')->getNavbar(); /* devilbox edit */?>
@ -766,6 +768,6 @@ $opcache = OpCacheService::init($options);
var filesObj = ReactDOM.render(React.createElement(Files, null), document.getElementById('filelist'));
ReactDOM.render(React.createElement(Directives, null), document.getElementById('directives'));
</script>
<?php require '../include/footer.php'; ?>
<?php echo loadClass('Html')->getFooter(); /* devilbox edit */?>
</body>
</html>

View File

@ -1,22 +0,0 @@
<?php require '../config.php'; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php require '../include/head.php'; ?>
</head>
<body>
<?php require '../include/navigation.php'; ?>
<div class="container">
<div class="row">
<div class="col-md-12">
<?php phpinfo(); ?>
</div>
</div>
</div><!-- /.container -->
<?php require '../include/footer.php'; ?>
</body>
</html>

View File

@ -0,0 +1,190 @@
<?php require '../config.php'; ?>
<?php loadClass('Helper')->authPage(); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<?php echo loadClass('Html')->getHead(true); ?>
</head>
<body>
<?php echo loadClass('Html')->getNavbar(); ?>
<div class="container">
<h1>Support</h1>
<br/>
<p>I am currently the sole creator and maintainer of the Devilbox and all of its required projects.<br/>If you find this useful or if it makes your daily programming life easier, consider donating to keep this project alive.</p>
<ul>
<li><a target="_blank" href="https://github.com/sponsors/cytopia"><strong>GitHub sponsorship</strong></a></li>
<li><a target="_blank" href="https://www.patreon.com/devilbox"><strong>Patreon</strong></a></li>
</ul>
<br/>
<div class="row">
<div class="col-md-6">
<h2>Core projects</h2>
<p>The following core projects were created and are maintained in order to make the Devilbox work.</p>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Repository</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/devilbox">devilbox</a></td>
<td>The Devilbox</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-5.2">docker-php-fpm-5.2</a></td>
<td>Legacy PHP 5.2 base images (amd64 and i386)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-5.3">docker-php-fpm-5.3</a></td>
<td>Legacy PHP 5.3 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-5.4">docker-php-fpm-5.4</a></td>
<td>Legacy PHP 5.4 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-5.5">docker-php-fpm-5.5</a></td>
<td>Legacy PHP 5.5 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-8.0">docker-php-fpm-8.0</a></td>
<td>PHP 8.0 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-8.1">docker-php-fpm-8.1</a></td>
<td>PHP 8.1 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm-8.2">docker-php-fpm-8.2</a></td>
<td>Upcoming PHP 8.2 base images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-fpm">docker-php-fpm</a></td>
<td>PHP-FPM Devilbox images</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-mysql">docker-mysql</a></td>
<td>MySQL, MariaDB and PerconaDB images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-apache-2.2">docker-apache-2.2</a></td>
<td>Apache 2.2 images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-apache-2.4">docker-apache-2.4</a></td>
<td>Apache 2.4 images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-nginx-stable">docker-nginx-stable</a></td>
<td>Nginx stable images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-nginx-mainline">docker-nginx-mainline</a></td>
<td>Nginx mainline images (amd64 and arm64)</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-haproxy">docker-haproxy</a></td>
<td>HA Proxy image</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-ngrok">docker-ngrok</a></td>
<td>Ngrok image</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-varnish">docker-varnish</a></td>
<td>Varnish image</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-python-flask">docker-python-flask</a></td>
<td>Python Flask image</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<h2>Supporting projects</h2>
<p>The following supporting projects were created and are maintained in order to keep the Devilbox eco system running.</p>
<table class="table table-striped ">
<thead class="thead-inverse ">
<tr>
<th>Repository</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/cert-gen">cert-gen</a></td>
<td>CA and cert generation tool</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/vhost-gen">vhost-gen</a></td>
<td>HTTPD agnostic vhost creation tool</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/watcherd">watcherd</a></td>
<td>OS agnostic filesystem change poller tool</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/makefiles">makefiles</a></td>
<td>Unified build Makefiles</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/github-actions">github-actions</a></td>
<td>Re-usable GitHub Action Workflows</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/shell-command-retry-action">shell-command-retry-action</a></td>
<td>GitHub Action</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/docker-tag-action">docker-tag-action</a></td>
<td>GitHub Action</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/git-ref-matrix-action">git-ref-matrix-action</a></td>
<td>GitHub Action</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-python-sphinx">docker-python-sphinx</a></td>
<td>Dockerized Sphinx documentation builder</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/xdebug">xdebug</a></td>
<td>IP addr alias MacOS plist for Xdebug</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/docker-ansible">docker-ansible</a></td>
<td>Ansible images for PHP-FPM Dockerfile creation</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/linkcheck">linkcheck</a></td>
<td>Broken linkchecker for documentation</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/cytopia/docker-linkcheck">docker-linkcheck</a></td>
<td>Dockerized version of linkcheck</td>
</tr>
<tr>
<td><i class="fa fa-github-alt" aria-hidden="true"></i> <a target="_blank" href="https://github.com/devilbox/docker-php-1.99s">docker-php-1.99s</a></td>
<td>Just for the lulz</td>
</tr>
</tbody>
</table>
</div>
</div>
</div><!-- /.container -->
<?php echo loadClass('Html')->getFooter(); ?>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,::after,::before{-webkit-box-sizing:inherit;box-sizing:inherit}@-ms-viewport{width:device-width}html{-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:1rem;font-weight:400;line-height:1.5;color:#292b2c;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{cursor:help}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}a{color:#0275d8;text-decoration:none}a:focus,a:hover{color:#014c8c;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle}[role=button]{cursor:pointer}[role=button],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation;touch-action:manipulation}table{border-collapse:collapse;background-color:transparent}caption{padding-top:.75rem;padding-bottom:.75rem;color:#636c72;text-align:left;caption-side:bottom}th{text-align:left}label{display:inline-block;margin-bottom:.5rem}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,select,textarea{line-height:inherit}input[type=checkbox]:disabled,input[type=radio]:disabled{cursor:not-allowed}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit}input[type=search]{-webkit-appearance:none}output{display:inline-block}[hidden]{display:none!important}/*# sourceMappingURL=bootstrap-reboot.min.css.map */

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../scss/_normalize.scss","bootstrap-reboot.css","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss"],"names":[],"mappings":"4EAYA,KACE,YAAA,WACA,YAAA,KACA,qBAAA,KACA,yBAAA,KAUF,KACE,OAAA,EAOF,QAAA,MAAA,OAAA,OAAA,IAAA,QAME,QAAA,MAQF,GACE,UAAA,IACA,OAAA,MAAA,EAWF,WAAA,OAAA,KAGE,QAAA,MAOF,OACE,OAAA,IAAA,KAQF,GACE,mBAAA,YAAA,WAAA,YACA,OAAA,EACA,SAAA,QAQF,IACE,YAAA,UAAA,UACA,UAAA,IAWF,EACE,iBAAA,YACA,6BAAA,QAQF,SAAA,QAEE,cAAA,EAQF,YACE,cAAA,KACA,gBAAA,UACA,gBAAA,UAAA,OAOF,EAAA,OAEE,YAAA,QAOF,EAAA,OAEE,YAAA,OAQF,KAAA,IAAA,KAGE,YAAA,UAAA,UACA,UAAA,IAOF,IACE,WAAA,OAOF,KACE,iBAAA,KACA,MAAA,KAOF,MACE,UAAA,IAQF,IAAA,IAEE,UAAA,IACA,YAAA,EACA,SAAA,SACA,eAAA,SAGF,IACE,OAAA,OAGF,IACE,IAAA,MAUF,MAAA,MAEE,QAAA,aAOF,sBACE,QAAA,KACA,OAAA,EAOF,IACE,aAAA,KAOF,eACE,SAAA,OAWF,OAAA,MAAA,SAAA,OAAA,SAKE,YAAA,WACA,UAAA,KACA,YAAA,KACA,OAAA,EAQF,OAAA,MAEE,SAAA,QAQF,OAAA,OAEE,eAAA,KASF,aAAA,cAAA,OAAA,mBAIE,mBAAA,OAOF,gCAAA,+BAAA,gCAAA,yBAIE,aAAA,KACA,QAAA,EAOF,6BAAA,4BAAA,6BAAA,sBAIE,QAAA,IAAA,OAAA,WAOF,SACE,OAAA,IAAA,MAAA,OACA,OAAA,EAAA,IACA,QAAA,MAAA,OAAA,MAUF,OACE,mBAAA,WAAA,WAAA,WACA,MAAA,QACA,QAAA,MACA,UAAA,KACA,QAAA,EACA,YAAA,OAQF,SACE,QAAA,aACA,eAAA,SAOF,SACE,SAAA,KCrKF,gBAAA,aD+KE,mBAAA,WAAA,WAAA,WACA,QAAA,EC1KF,yCAAA,yCDmLE,OAAA,KC9KF,cDuLE,mBAAA,UACA,eAAA,KCnLF,4CAAA,yCD4LE,mBAAA,KAQF,6BACE,mBAAA,OACA,KAAA,QAWF,QAAA,KAEE,QAAA,MAOF,QACE,QAAA,UAUF,OACE,QAAA,aAOF,SACE,QAAA,KCnNF,SD8NE,QAAA,KEtbF,KACE,mBAAA,WAAA,WAAA,WAGF,EAAA,QAAA,SAGE,mBAAA,QAAA,WAAA,QAoBA,cAAgB,MAAA,aAQlB,KAYE,mBAAA,UAGA,4BAAA,YAGF,KACE,YAAA,cAAA,UAAA,mBAAA,WAAA,OC2K4H,iBD3K5H,MAAA,WACA,UAAA,KACA,YAAA,IACA,YAAA,IAEA,MAAA,QAEA,iBAAA,KD2LF,sBClLE,QAAA,YAYF,GAAI,GAAI,GAAI,GAAI,GAAI,GAClB,WAAA,EACA,cAAA,MAOF,EACE,WAAA,EACA,cAAA,KAIF,0BAAA,YAGE,OAAA,KAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAGF,GAAA,GAAA,GAGE,WAAA,EACA,cAAA,KAGF,MAAA,MAAA,MAAA,MAIE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAQF,EACE,MAAA,QACA,gBAAA,KEhJE,QAAA,QFmJA,MAAA,QACA,gBAAA,UAUJ,8BACE,MAAA,QACA,gBAAA,KEhKE,oCAAA,oCFmKA,MAAA,QACA,gBAAA,KANJ,oCAUI,QAAA,EASJ,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAQF,OAGE,OAAA,EAAA,EAAA,KAQF,IAGE,eAAA,ODsIF,cCzHE,OAAA,QAcF,cAAA,EAAA,KAAA,OAAA,MAAA,MAAA,OAAA,QAAA,SASE,iBAAA,aAAA,aAAA,aAQF,MAEE,gBAAA,SAEA,iBAAA,YAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAEE,WAAA,KAQF,MAEE,QAAA,aACA,cAAA,MAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBAGF,OAAA,MAAA,OAAA,SAME,YAAA,QAGF,8BAAA,2BAMI,OAAA,YAKJ,iBAAA,iBAAA,2BAAA,kBASE,mBAAA,QAGF,SAEE,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAGF,OAEE,QAAA,MACA,MAAA,KACA,QAAA,EACA,cAAA,MACA,UAAA,OACA,YAAA,QAGF,mBAKE,mBAAA,KAIF,OACE,QAAA,aDsEF,SC9DE,QAAA"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

391
.devilbox/www/htdocs/vendor/ocp.php vendored Normal file
View File

@ -0,0 +1,391 @@
<?php
/*
OCP - Opcache Control Panel (aka Zend Optimizer+ Control Panel for PHP)
Author: _ck_ (with contributions by GK, stasilok)
Version: 0.1.7
Free for any kind of use or modification, I am not responsible for anything, please share your improvements
* revision history
0.1.7 2015-09-01 regex fix for PHP7 phpinfo
0.1.6 2013-04-12 moved meta to footer so graphs can be higher and reduce clutter
0.1.5 2013-04-12 added graphs to visualize cache state, please report any browser/style bugs
0.1.4 2013-04-09 added "recheck" to update files when using large revalidate_freq (or validate_timestamps=Off)
0.1.3 2013-03-30 show host and php version, can bookmark with hashtag ie. #statistics - needs new layout asap
0.1.2 2013-03-25 show optimization levels, number formatting, support for start_time in 7.0.2
0.1.1 2013-03-18 today Zend completely renamed Optimizer+ to OPcache, adjusted OCP to keep working
0.1.0 2013-03-17 added group/sort indicators, replaced "accelerator_" functions with "opcache_"
0.0.6 2013-03-16 transition support as Zend renames product and functions for PHP 5.5 (stasilok)
0.0.5 2013-03-10 added refresh button (GK)
0.0.4 2013-02-18 added file grouping and sorting (click on headers) - code needs cleanup but gets the job done
0.0.2 2013-02-14 first public release
* known problems/limitations:
Unlike APC, the Zend OPcache API
- cannot determine when a file was put into the cache
- cannot change settings on the fly
- cannot protect opcache functions by restricting execution to only specific scripts/paths
* todo:
Extract variables for prefered ordering and better layout instead of just dumping into tables
File list filter
*/
// ini_set('display_errors',1); error_reporting(-1);
if ( count(get_included_files())>1 || php_sapi_name()=='cli' || empty($_SERVER['REMOTE_ADDR']) ) { die; } // weak block against indirect access
$time=time();
define('CACHEPREFIX',function_exists('opcache_reset')?'opcache_':(function_exists('accelerator_reset')?'accelerator_':''));
if ( !empty($_GET['RESET']) ) {
if ( function_exists(CACHEPREFIX.'reset') ) { call_user_func(CACHEPREFIX.'reset'); }
header( 'Location: '.str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) );
exit;
}
if ( !empty($_GET['RECHECK']) ) {
if ( function_exists(CACHEPREFIX.'invalidate') ) {
$recheck=trim($_GET['RECHECK']); $files=call_user_func(CACHEPREFIX.'get_status');
if (!empty($files['scripts'])) {
foreach ($files['scripts'] as $file=>$value) {
if ( $recheck==='1' || strpos($file,$recheck)===0 ) call_user_func(CACHEPREFIX.'invalidate',$file);
}
}
header( 'Location: '.str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) );
} else { echo 'Sorry, this feature requires Zend Opcache newer than April 8th 2013'; }
exit;
}
?><!DOCTYPE html>
<html>
<head>
<title>OCP - Opcache Control Panel</title>
<meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" />
<style type="text/css">
body {background-color: #fff; color: #000;}
body, td, th, h1, h2 {font-family: sans-serif;}
pre {margin: 0px; font-family: monospace;}
a:link,a:visited {color: #000099; text-decoration: none;}
a:hover {text-decoration: underline;}
table {border-collapse: collapse; width: 600px; }
.center {text-align: center;}
.center table { margin-left: auto; margin-right: auto; text-align: left;}
.center th { text-align: center !important; }
.middle {vertical-align:middle;}
td, th { border: 1px solid #000; font-size: 75%; vertical-align: baseline; padding: 3px; }
h1 {font-size: 150%;}
h2 {font-size: 125%;}
.p {text-align: left;}
.e {background-color: #ccccff; font-weight: bold; color: #000; width:50%; white-space:nowrap;}
.h {background-color: #9999cc; font-weight: bold; color: #000;}
.v {background-color: #cccccc; color: #000;}
.vr {background-color: #cccccc; text-align: right; color: #000; white-space: nowrap;}
.b {font-weight:bold;}
.white, .white a {color:#fff;}
img {float: right; border: 0px;}
hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000;}
.meta, .small {font-size: 75%; }
.meta {margin: 2em 0;}
.meta a, th a {padding: 10px; white-space:nowrap; }
.buttons {margin:0 0 1em;}
.buttons a {margin:0 15px; background-color: #9999cc; color:#fff; text-decoration:none; padding:1px; border:1px solid #000; display:inline-block; width:5em; text-align:center;}
#files td.v a {font-weight:bold; color:#9999cc; margin:0 10px 0 5px; text-decoration:none; font-size:120%;}
#files td.v a:hover {font-weight:bold; color:#ee0000;}
.graph {display:inline-block; width:145px; margin:1em 0 1em 1px; border:0; vertical-align:top;}
.graph table {width:100%; height:150px; border:0; padding:0; margin:5px 0 0 0; position:relative;}
.graph td {vertical-align:middle; border:0; padding:0 0 0 5px;}
.graph .bar {width:25px; text-align:right; padding:0 2px; color:#fff;}
.graph .total {width:34px; text-align:center; padding:0 5px 0 0;}
.graph .total div {border:1px dashed #888; border-right:0; height:99%; width:12px; position:absolute; bottom:0; left:17px; z-index:-1;}
.graph .total span {background:#fff; font-weight:bold;}
.graph .actual {text-align:right; font-weight:bold; padding:0 5px 0 0;}
.graph .red {background:#ee0000;}
.graph .green {background:#00cc00;}
.graph .brown {background:#8B4513;}
</style>
<!--[if lt IE 9]><script type="text/javascript" defer="defer">
window.onload=function(){var i,t=document.getElementsByTagName('table');for(i=0;i<t.length;i++){if(t[i].parentNode.className=='graph')t[i].style.height=150-(t[i].clientHeight-150)+'px';}}
</script><![endif]-->
</head>
<body>
<div class="center">
<h1><a href="?">Opcache Control Panel</a></h1>
<div class="buttons">
<a href="?ALL=1">Details</a>
<a href="?FILES=1&GROUP=2&SORT=3">Files</a>
<a href="?RESET=1" onclick="return confirm('RESET cache ?')">Reset</a>
<?php if ( function_exists(CACHEPREFIX.'invalidate') ) { ?>
<a href="?RECHECK=1" onclick="return confirm('Recheck all files in the cache ?')">Recheck</a>
<?php } ?>
<a href="?" onclick="window.location.reload(true); return false">Refresh</a>
</div>
<?php
if ( !function_exists(CACHEPREFIX.'get_status') ) { echo '<h2>Opcache not detected?</h2>'; die; }
if ( !empty($_GET['FILES']) ) { echo '<h2>files cached</h2>'; files_display(); echo '</div></body></html>'; exit; }
if ( !(isset($_REQUEST['GRAPHS']) && !$_REQUEST['GRAPHS']) && CACHEPREFIX=='opcache_') { graphs_display(); if ( !empty($_REQUEST['GRAPHS']) ) { exit; } }
ob_start(); phpinfo(8); $phpinfo = ob_get_contents(); ob_end_clean(); // some info is only available via phpinfo? sadly buffering capture has to be used
if ( !preg_match( '/module\_Zend.(Optimizer\+|OPcache).+?(\<table[^>]*\>.+?\<\/table\>).+?(\<table[^>]*\>.+?\<\/table\>)/is', $phpinfo, $opcache) ) { } // todo
if ( function_exists(CACHEPREFIX.'get_configuration') ) { echo '<h2>general</h2>'; $configuration=call_user_func(CACHEPREFIX.'get_configuration'); }
$host=function_exists('gethostname')?@gethostname():@php_uname('n'); if (empty($host)) { $host=empty($_SERVER['SERVER_NAME'])?$_SERVER['HOST_NAME']:$_SERVER['SERVER_NAME']; }
$version=array('Host'=>$host);
$version['PHP Version']='PHP '.(defined('PHP_VERSION')?PHP_VERSION:'???').' '.(defined('PHP_SAPI')?PHP_SAPI:'').' '.(defined('PHP_OS')?' '.PHP_OS:'');
$version['Opcache Version']=empty($configuration['version']['version'])?'???':$configuration['version'][CACHEPREFIX.'product_name'].' '.$configuration['version']['version'];
print_table($version);
if ( !empty($opcache[2]) ) { echo preg_replace('/\<tr\>\<td class\="e"\>[^>]+\<\/td\>\<td class\="v"\>[0-9\,\. ]+\<\/td\>\<\/tr\>/','',$opcache[2]); }
if ( function_exists(CACHEPREFIX.'get_status') && $status=call_user_func(CACHEPREFIX.'get_status') ) {
$uptime=array();
if ( !empty($status[CACHEPREFIX.'statistics']['start_time']) ) {
$uptime['uptime']=time_since($time,$status[CACHEPREFIX.'statistics']['start_time'],1,'');
}
if ( !empty($status[CACHEPREFIX.'statistics']['last_restart_time']) ) {
$uptime['last_restart']=time_since($time,$status[CACHEPREFIX.'statistics']['last_restart_time']);
}
if (!empty($uptime)) {print_table($uptime);}
if ( !empty($status['cache_full']) ) { $status['memory_usage']['cache_full']=$status['cache_full']; }
echo '<h2 id="memory">memory</h2>';
print_table($status['memory_usage']);
unset($status[CACHEPREFIX.'statistics']['start_time'],$status[CACHEPREFIX.'statistics']['last_restart_time']);
echo '<h2 id="statistics">statistics</h2>';
print_table($status[CACHEPREFIX.'statistics']);
}
if ( empty($_GET['ALL']) ) { meta_display(); exit; }
if ( !empty($configuration['blacklist']) ) { echo '<h2 id="blacklist">blacklist</h2>'; print_table($configuration['blacklist']); }
if ( !empty($opcache[3]) ) { echo '<h2 id="runtime">runtime</h2>'; echo $opcache[3]; }
$name='zend opcache'; $functions=get_extension_funcs($name);
if (!$functions) { $name='zend optimizer+'; $functions=get_extension_funcs($name); }
if ($functions) { echo '<h2 id="functions">functions</h2>'; print_table($functions); } else { $name=''; }
$level=trim(CACHEPREFIX,'_').'.optimization_level';
if (isset($configuration['directives'][$level])) {
echo '<h2 id="optimization">optimization levels</h2>';
$levelset=strrev(base_convert($configuration['directives'][$level], 10, 2));
$levels=array(
1=>'<a href="http://wikipedia.org/wiki/Common_subexpression_elimination">Constants subexpressions elimination</a> (CSE) true, false, null, etc.<br />Optimize series of ADD_STRING / ADD_CHAR<br />Convert CAST(IS_BOOL,x) into BOOL(x)<br />Convert <a href="http://www.php.net/manual/internals2.opcodes.init-fcall-by-name.php">INIT_FCALL_BY_NAME</a> + <a href="http://www.php.net/manual/internals2.opcodes.do-fcall-by-name.php">DO_FCALL_BY_NAME</a> into <a href="http://www.php.net/manual/internals2.opcodes.do-fcall.php">DO_FCALL</a>',
2=>'Convert constant operands to expected types<br />Convert conditional <a href="http://php.net/manual/internals2.opcodes.jmp.php">JMP</a> with constant operands<br />Optimize static <a href="http://php.net/manual/internals2.opcodes.brk.php">BRK</a> and <a href="<a href="http://php.net/manual/internals2.opcodes.cont.php">CONT</a>',
3=>'Convert $a = $a + expr into $a += expr<br />Convert $a++ into ++$a<br />Optimize series of <a href="http://php.net/manual/internals2.opcodes.jmp.php">JMP</a>',
4=>'PRINT and ECHO optimization (<a href="https://github.com/zend-dev/ZendOptimizerPlus/issues/73">defunct</a>)',
5=>'Block Optimization - most expensive pass<br />Performs many different optimization patterns based on <a href="http://wikipedia.org/wiki/Control_flow_graph">control flow graph</a> (CFG)',
9=>'Optimize <a href="http://wikipedia.org/wiki/Register_allocation">register allocation</a> (allows re-usage of temporary variables)',
10=>'Remove NOPs'
);
echo '<table width="600" border="0" cellpadding="3"><tbody><tr class="h"><th>Pass</th><th>Description</th></tr>';
foreach ($levels as $pass=>$description) {
$disabled=substr($levelset,$pass-1,1)!=='1' || $pass==4 ? ' white':'';
echo '<tr><td class="v center middle'.$disabled.'">'.$pass.'</td><td class="v'.$disabled.'">'.$description.'</td></tr>';
}
echo '</table>';
}
if ( isset($_GET['DUMP']) ) {
if ($name) { echo '<h2 id="ini">ini</h2>'; print_table(ini_get_all($name,true)); }
foreach ($configuration as $key=>$value) { echo '<h2>',$key,'</h2>'; print_table($configuration[$key]); }
exit;
}
meta_display();
echo '</div></body></html>';
exit;
function time_since($time,$original,$extended=0,$text='ago') {
$time = $time - $original;
$day = $extended? floor($time/86400) : round($time/86400,0);
$amount=0; $unit='';
if ( $time < 86400) {
if ( $time < 60) { $amount=$time; $unit='second'; }
elseif ( $time < 3600) { $amount=floor($time/60); $unit='minute'; }
else { $amount=floor($time/3600); $unit='hour'; }
}
elseif ( $day < 14) { $amount=$day; $unit='day'; }
elseif ( $day < 56) { $amount=floor($day/7); $unit='week'; }
elseif ( $day < 672) { $amount=floor($day/30); $unit='month'; }
else { $amount=intval(2*($day/365))/2; $unit='year'; }
if ( $amount!=1) {$unit.='s';}
if ($extended && $time>60) { $text=' and '.time_since($time,$time<86400?($time<3600?$amount*60:$amount*3600):$day*86400,0,'').$text; }
return $amount.' '.$unit.' '.$text;
}
function print_table($array,$headers=false) {
if ( empty($array) || !is_array($array) ) {return;}
echo '<table border="0" cellpadding="3" width="600">';
if (!empty($headers)) {
if (!is_array($headers)) {$headers=array_keys(reset($array));}
echo '<tr class="h">';
foreach ($headers as $value) { echo '<th>',$value,'</th>'; }
echo '</tr>';
}
foreach ($array as $key=>$value) {
echo '<tr>';
if ( !is_numeric($key) ) {
$key=ucwords(str_replace('_',' ',$key));
echo '<td class="e">',$key,'</td>';
if ( is_numeric($value) ) {
if ( $value>1048576) { $value=round($value/1048576,1).'M'; }
elseif ( is_float($value) ) { $value=round($value,1); }
}
}
if ( is_array($value) ) {
foreach ($value as $column) {
echo '<td class="v">',$column,'</td>';
}
echo '</tr>';
}
else { echo '<td class="v">',$value,'</td></tr>'; }
}
echo '</table>';
}
function files_display() {
$status=call_user_func(CACHEPREFIX.'get_status');
if ( empty($status['scripts']) ) {return;}
if ( isset($_GET['DUMP']) ) { print_table($status['scripts']); exit;}
$time=time(); $sort=0;
$nogroup=preg_replace('/\&?GROUP\=[\-0-9]+/','',$_SERVER['REQUEST_URI']);
$nosort=preg_replace('/\&?SORT\=[\-0-9]+/','',$_SERVER['REQUEST_URI']);
$group=empty($_GET['GROUP'])?0:intval($_GET['GROUP']); if ( $group<0 || $group>9) { $group=1;}
$groupset=array_fill(0,9,''); $groupset[$group]=' class="b" ';
echo '<div class="meta">
<a ',$groupset[0],'href="',$nogroup,'">ungroup</a> |
<a ',$groupset[1],'href="',$nogroup,'&GROUP=1">1</a> |
<a ',$groupset[2],'href="',$nogroup,'&GROUP=2">2</a> |
<a ',$groupset[3],'href="',$nogroup,'&GROUP=3">3</a> |
<a ',$groupset[4],'href="',$nogroup,'&GROUP=4">4</a> |
<a ',$groupset[5],'href="',$nogroup,'&GROUP=5">5</a>
</div>';
if ( !$group ) { $files =& $status['scripts']; }
else {
$files=array();
foreach ($status['scripts'] as $data) {
if ( preg_match('@^[/]([^/]+[/]){'.$group.'}@',$data['full_path'],$path) ) {
if ( empty($files[$path[0]])) { $files[$path[0]]=array('full_path'=>'','files'=>0,'hits'=>0,'memory_consumption'=>0,'last_used_timestamp'=>'','timestamp'=>''); }
$files[$path[0]]['full_path']=$path[0];
$files[$path[0]]['files']++;
$files[$path[0]]['memory_consumption']+=$data['memory_consumption'];
$files[$path[0]]['hits']+=$data['hits'];
if ( $data['last_used_timestamp']>$files[$path[0]]['last_used_timestamp']) {$files[$path[0]]['last_used_timestamp']=$data['last_used_timestamp'];}
if ( $data['timestamp']>$files[$path[0]]['timestamp']) {$files[$path[0]]['timestamp']=$data['timestamp'];}
}
}
}
if ( !empty($_GET['SORT']) ) {
$keys=array(
'full_path'=>SORT_STRING,
'files'=>SORT_NUMERIC,
'memory_consumption'=>SORT_NUMERIC,
'hits'=>SORT_NUMERIC,
'last_used_timestamp'=>SORT_NUMERIC,
'timestamp'=>SORT_NUMERIC
);
$titles=array('','path',$group?'files':'','size','hits','last used','created');
$offsets=array_keys($keys);
$key=intval($_GET['SORT']);
$direction=$key>0?1:-1;
$key=abs($key)-1;
$key=isset($offsets[$key])&&!($key==1&&empty($group))?$offsets[$key]:reset($offsets);
$sort=array_search($key,$offsets)+1;
$sortflip=range(0,7); $sortflip[$sort]=-$direction*$sort;
if ( $keys[$key]==SORT_STRING) {$direction=-$direction; }
$arrow=array_fill(0,7,''); $arrow[$sort]=$direction>0?' &#x25BC;':' &#x25B2;';
$direction=$direction>0?SORT_DESC:SORT_ASC;
$column=array(); foreach ($files as $data) { $column[]=$data[$key]; }
array_multisort($column, $keys[$key], $direction, $files);
}
echo '<table border="0" cellpadding="3" width="960" id="files">
<tr class="h">';
foreach ($titles as $column=>$title) {
if ($title) echo '<th><a href="',$nosort,'&SORT=',$sortflip[$column],'">',$title,$arrow[$column],'</a></th>';
}
echo ' </tr>';
foreach ($files as $data) {
echo '<tr>
<td class="v" nowrap><a title="recheck" href="?RECHECK=',rawurlencode($data['full_path']),'">x</a>',$data['full_path'],'</td>',
($group?'<td class="vr">'.number_format($data['files']).'</td>':''),
'<td class="vr">',number_format(round($data['memory_consumption']/1024)),'K</td>',
'<td class="vr">',number_format($data['hits']),'</td>',
'<td class="vr">',time_since($time,$data['last_used_timestamp']),'</td>',
'<td class="vr">',empty($data['timestamp'])?'':time_since($time,$data['timestamp']),'</td>
</tr>';
}
echo '</table>';
}
function graphs_display() {
$graphs=array();
$colors=array('green','brown','red');
$primes=array(223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987);
$configuration=call_user_func(CACHEPREFIX.'get_configuration');
$status=call_user_func(CACHEPREFIX.'get_status');
$graphs['memory']['total']=$configuration['directives']['opcache.memory_consumption'];
$graphs['memory']['free']=$status['memory_usage']['free_memory'];
$graphs['memory']['used']=$status['memory_usage']['used_memory'];
$graphs['memory']['wasted']=$status['memory_usage']['wasted_memory'];
$graphs['keys']['total']=$status[CACHEPREFIX.'statistics']['max_cached_keys'];
foreach ($primes as $prime) { if ($prime>=$graphs['keys']['total']) { $graphs['keys']['total']=$prime; break;} }
$graphs['keys']['free']=$graphs['keys']['total']-$status[CACHEPREFIX.'statistics']['num_cached_keys'];
$graphs['keys']['scripts']=$status[CACHEPREFIX.'statistics']['num_cached_scripts'];
$graphs['keys']['wasted']=$status[CACHEPREFIX.'statistics']['num_cached_keys']-$status[CACHEPREFIX.'statistics']['num_cached_scripts'];
$graphs['hits']['total']=0;
$graphs['hits']['hits']=$status[CACHEPREFIX.'statistics']['hits'];
$graphs['hits']['misses']=$status[CACHEPREFIX.'statistics']['misses'];
$graphs['hits']['blacklist']=$status[CACHEPREFIX.'statistics']['blacklist_misses'];
$graphs['hits']['total']=array_sum($graphs['hits']);
$graphs['restarts']['total']=0;
$graphs['restarts']['manual']=$status[CACHEPREFIX.'statistics']['manual_restarts'];
$graphs['restarts']['keys']=$status[CACHEPREFIX.'statistics']['hash_restarts'];
$graphs['restarts']['memory']=$status[CACHEPREFIX.'statistics']['oom_restarts'];
$graphs['restarts']['total']=array_sum($graphs['restarts']);
foreach ( $graphs as $caption=>$graph) {
echo '<div class="graph"><div class="h">',$caption,'</div><table border="0" cellpadding="0" cellspacing="0">';
foreach ($graph as $label=>$value) {
if ($label=='total') { $key=0; $total=$value; $totaldisplay='<td rowspan="3" class="total"><span>'.($total>999999?round($total/1024/1024).'M':($total>9999?round($total/1024).'K':$total)).'</span><div></div></td>'; continue;}
$percent=$total?floor($value*100/$total):''; $percent=!$percent||$percent>99?'':$percent.'%';
echo '<tr>',$totaldisplay,'<td class="actual">', ($value>999999?round($value/1024/1024).'M':($value>9999?round($value/1024).'K':$value)),'</td><td class="bar ',$colors[$key],'" height="',$percent,'">',$percent,'</td><td>',$label,'</td></tr>';
$key++; $totaldisplay='';
}
echo '</table></div>',"\n";
}
}
function meta_display() {
?>
<div class="meta">
<a href="http://files.zend.com/help/Zend-Server-6/content/zendoptimizerplus.html">directives guide</a> |
<a href="http://files.zend.com/help/Zend-Server-6/content/zend_optimizer+_-_php_api.htm">functions guide</a> |
<a href="https://wiki.php.net/rfc/optimizerplus">wiki.php.net</a> |
<a href="http://pecl.php.net/package/ZendOpcache">pecl</a> |
<a href="https://github.com/zend-dev/ZendOptimizerPlus/">Zend source</a> |
<a href="https://gist.github.com/ck-on/4959032/?ocp.php">OCP latest</a>
</div>
<?php
}

View File

@ -0,0 +1,26 @@
<?php
error_reporting(E_ALL & ~E_WARNING & ~E_NOTICE);
return array (
'stats_api' => 'Server',
'slabs_api' => 'Server',
'items_api' => 'Server',
'get_api' => 'Server',
'set_api' => 'Server',
'delete_api' => 'Server',
'flush_all_api' => 'Server',
'connection_timeout' => 1,
'max_item_dump'=> 100,
'refresh_rate' => 2,
'memory_alert' => 80,
'hit_rate_alert' => 90,
'eviction_alert' => 0,
'file_path' => '/tmp',
'servers' => array (
'Devilbox Memcached' => array (
'memcd' => array (
'hostname' => 'memcd',
'port' => '11211',
),
),
),
);

View File

@ -0,0 +1,30 @@
<?php
# Headers
header('Content-type: text/html;');
header('Cache-Control: no-cache, must-revalidate');
# Constants declaration
define('CURRENT_VERSION', '1.3.0');
# PHP < 5.3 Compatibility
if (defined('ENT_IGNORE') === false) {
define('ENT_IGNORE', 0);
}
# XSS / User input check
foreach ($_REQUEST as $index => $data) {
$_REQUEST[$index] = htmlentities($data);
}
# Autoloader
function autoloader($class)
{
require_once str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
}
spl_autoload_register('autoloader');
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Date timezone
date_default_timezone_set('Europe/Paris');

View File

@ -0,0 +1,110 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Factory for communication with Memcache Server
*
* @author elijaa@free.fr
* @since 30/03/2010
*/
class Library_Command_Factory
{
private static $_object = array();
# No explicit call of constructor
private function __construct()
{}
# No explicit call of clone()
private function __clone()
{}
/**
* Accessor to command class instance by command type
*
* @param String $command Type of command
*
* @return void
*/
public static function instance($command)
{
# Importing configuration
$_ini = Library_Configuration_Loader::singleton();
# Instance does not exists
if (! isset(self::$_object[$_ini->get($command)]) || ($_ini->get($command) != 'Server')) {
# Switching by API
switch ($_ini->get($command)) {
case 'Memcache' :
# PECL Memcache API
require_once 'Memcache.php';
self::$_object['Memcache'] = new Library_Command_Memcache();
break;
case 'Memcached' :
# PECL Memcached API
require_once 'Memcached.php';
self::$_object['Memcached'] = new Library_Command_Memcached();
break;
case 'Server' :
default :
# Server API (eg communicating directly with the memcache server)
require_once 'Server.php';
self::$_object['Server'] = new Library_Command_Server();
break;
}
}
return self::$_object[$_ini->get($command)];
}
/**
* Accessor to command class instance by type
*
* @param String $command Type of command
*
* @return void
*/
public static function api($api)
{
# Instance does not exists
if (! isset(self::$_object[$api]) || ($api != 'Server')) {
# Switching by API
switch ($api) {
case 'Memcache' :
# PECL Memcache API
require_once 'Memcache.php';
self::$_object['Memcache'] = new Library_Command_Memcache();
break;
case 'Memcached' :
# PECL Memcached API
require_once 'Memcached.php';
self::$_object['Memcached'] = new Library_Command_Memcached();
break;
case 'Server' :
default :
# Server API (eg communicating directly with the memcache server)
require_once 'Server.php';
self::$_object['Server'] = new Library_Command_Server();
break;
}
}
return self::$_object[$api];
}
}

View File

@ -0,0 +1,178 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Interface of communication to MemCache Server
*
* @author elijaa@free.fr
* @since 20/03/2010
*/
interface Library_Command_Interface
{
/**
* Constructor
*
* @return void
*/
function __construct();
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
function stats($server, $port);
/**
* Send stats settings command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function settings($server, $port);
/**
* Retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
function slabs($server, $port);
/**
* Retrieve items from a slabs
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $slab Slab ID
*
* @return Array|Boolean
*/
function items($server, $port, $slab);
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
function get($server, $port, $key);
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration);
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
function delete($server, $port, $key);
/**
* Increment the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to increment
* @param Integer $value Value to increment
*
* @return String
*/
function increment($server, $port, $key, $value);
/**
* Decrement the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to decrement
* @param Integer $value Value to decrement
*
* @return String
*/
function decrement($server, $port, $key, $value);
/**
* Flush all items on a server after delay
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay);
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
* @param Boolean $level Level of detail
* @param Boolean $more More action
*
* @return array
*/
function search($server, $port, $search, $level = false, $more = false);
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command);
}

View File

@ -0,0 +1,309 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache
*
* @author elijaa@free.fr
* @since 20/03/2010
*/
class Library_Command_Memcache implements Library_Command_Interface
{
private static $_ini;
private static $_memcache;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
# Initializing
self::$_memcache = new Memcache();
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command
if (($return = self::$_memcache->getExtendedStats())) {
# Delete server key based
$stats = $return[$server . ':' . $port];
return $stats;
}
return false;
}
/**
* Send stats settings command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function settings($server, $port)
{
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
# Initializing
$slabs = array();
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : slabs
if (($slabs = self::$_memcache->getStats('slabs'))) {
# Finding uptime
$stats = $this->stats($server, $port);
$slabs['uptime'] = $stats['uptime'];
unset($stats);
# Executing command : items
if (($result = self::$_memcache->getStats('items'))) {
# Indexing by slabs
foreach ($result['items'] as $id => $items) {
foreach ($items as $key => $value) {
$slabs[$id]['items:' . $key] = $value;
}
}
return $slabs;
}
}
return false;
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
# Initializing
$items = false;
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : slabs stats
if (($items = self::$_memcache->getStats('cachedump', $slab, self::$_ini->get('max_item_dump')))) {
return $items;
}
return false;
}
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : get
if ($item = self::$_memcache->get($key)) {
return print_r($item, true);
}
return 'NOT_FOUND';
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : set
if (self::$_memcache->set($key, $data, 0, $duration)) {
return 'STORED';
}
return 'ERROR';
}
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
if (self::$_memcache->delete($key)) {
return 'DELETED';
}
return 'NOT_FOUND';
}
/**
* Increment the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to increment
* @param Integer $value Value to increment
*
* @return String
*/
function increment($server, $port, $key, $value)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : increment
if ($result = self::$_memcache->increment($key, $value)) {
return $result;
}
return 'NOT_FOUND';
}
/**
* Decrement the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to decrement
* @param Integer $value Value to decrement
*
* @return String
*/
function decrement($server, $port, $key, $value)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : decrement
if ($result = self::$_memcache->decrement($key, $value)) {
return $result;
}
return 'NOT_FOUND';
}
/**
* Flush all items on a server
* Warning, delay won't work with Memcache API
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : flush_all
self::$_memcache->flush();
return 'OK';
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return array
*/
function search($server, $port, $search, $level = false, $more = false)
{
throw new Exception('PECL Memcache does not support search function, use Server instead');
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
throw new Exception('PECL Memcache does not support telnet, use Server instead');
}
}

View File

@ -0,0 +1,287 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server via PECL memcache API http://pecl.php.net/package/memcache
*
* @author elijaa@free.fr
* @since 20/03/2010
*/
class Library_Command_Memcached implements Library_Command_Interface
{
private static $_ini;
private static $_memcache;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
# Initializing
self::$_memcache = new Memcached();
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command
if (($return = self::$_memcache->getStats())) {
# Delete server key based
$stats = $return[$server . ':' . $port];
# Adding value that miss
$stats['delete_hits'] = '';
$stats['delete_misses'] = '';
$stats['incr_hits'] = '';
$stats['incr_misses'] = '';
$stats['decr_hits'] = '';
$stats['decr_misses'] = '';
$stats['cas_hits'] = '';
$stats['cas_misses'] = '';
$stats['cas_badval'] = '';
return $stats;
}
return false;
}
/**
* Send stats settings command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function settings($server, $port)
{
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
throw new Exception('PECL Memcache does not support slabs stats, use Server or Memcache instead');
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
throw new Exception('PECL Memcache does not support slabs items stats, use Server or Memcache instead');
}
/**
* Send get command to server to retrieve an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : get
if ($item = self::$_memcache->get($key)) {
return print_r($item, true);
}
return self::$_memcache->getResultMessage();
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Checking duration
if ($duration == '') {
$duration = 0;
}
# Executing command : set
self::$_memcache->set($key, $data, $duration);
return self::$_memcache->getResultMessage();
}
/**
* Delete an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
self::$_memcache->delete($key);
return self::$_memcache->getResultMessage();
}
/**
* Increment the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to increment
* @param Integer $value Value to increment
*
* @return String
*/
function increment($server, $port, $key, $value)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : increment
if ($result = self::$_memcache->increment($key, $value)) {
return $result;
}
return self::$_memcache->getResultMessage();
}
/**
* Decrement the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to decrement
* @param Integer $value Value to decrement
*
* @return String
*/
function decrement($server, $port, $key, $value)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : decrement
if ($result = self::$_memcache->decrement($key, $value)) {
return $result;
}
return self::$_memcache->getResultMessage();
}
/**
* Flush all items on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
public function flush_all($server, $port, $delay)
{
# Adding server
self::$_memcache->addServer($server, $port);
# Executing command : delete
self::$_memcache->flush($delay);
return self::$_memcache->getResultMessage();
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
*
* @return Array
*/
function search($server, $port, $search, $level = false, $more = false)
{
throw new Exception('PECL Memcached does not support search function, use Server instead');
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
throw new Exception('PECL Memcached does not support telnet, use Server instead');
}
}

View File

@ -0,0 +1,486 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Sending command to memcache server
*
* @author elijaa@free.fr
* @since 20/03/2010
*/
class Library_Command_Server implements Library_Command_Interface
{
private static $_ini;
private static $_log;
/**
* Constructor
*
* @param Array $ini Array from ini_parse
*
* @return void
*/
public function __construct()
{
# Importing configuration
self::$_ini = Library_Configuration_Loader::singleton();
}
/**
* Executing a Command on a MemCache Server
* With the help of http://github.com/memcached/memcached/blob/master/doc/protocol.txt
* Return the response, or false otherwise
*
* @param String $command Command
* @param String $server Server Hostname
* @param Integer $port Server Port
*
* @return String|Boolean
*/
public function exec($command, $server, $port)
{
# Variables
$buffer = '';
$handle = null;
# Socket Opening
if (! ($handle = @fsockopen($server, $port, $errno, $errstr, self::$_ini->get('connection_timeout')))) {
# Adding error to log
self::$_log = utf8_encode($errstr);
Library_Data_Error::add(utf8_encode($errstr));
return false;
}
# Sending Command ...
fwrite($handle, $command . "\r\n");
# Getting first line
$buffer = fgets($handle);
# Checking if result is valid
if ($this->end($buffer, $command)) {
# Closing socket
fclose($handle);
# Adding error to log
self::$_log = $buffer;
return false;
}
# Reading Results
while ((! feof($handle))) {
# Getting line
$line = fgets($handle);
$buffer .= $line;
# Checking for end of MemCache command
if ($this->end($line, $command)) {
break;
}
}
# Closing socket
fclose($handle);
return $buffer;
}
/**
* Check if response is at the end from memcached server
* Return true if response end, true otherwise
*
* @param String $buffer Buffer received from memcached server
* @param String $command Command issued to memcached server
*
* @return Boolean
*/
private function end($buffer, $command)
{
# incr or decr also return integer
if ((preg_match('/^(incr|decr)/', $command))) {
if (preg_match('/^(END|ERROR|SERVER_ERROR|CLIENT_ERROR|NOT_FOUND|[0-9]*)/', $buffer)) {
return true;
}
} else {
# Checking command response end
if (preg_match('/^(END|DELETED|OK|ERROR|SERVER_ERROR|CLIENT_ERROR|NOT_FOUND|STORED|RESET|TOUCHED)/', $buffer)) {
return true;
}
}
return false;
}
/**
* Parse result to make an array
*
* @param String $string String to parse
* @param Boolean $string (optionnal) Parsing stats ?
*
* @return Array
*/
public function parse($string, $stats = true)
{
# Variable
$return = array();
# Exploding by \r\n
$lines = preg_split('/\r\n/', $string);
# Stats
if ($stats) {
# Browsing each line
foreach ($lines as $line) {
$data = preg_split('/ /', $line);
if (isset($data[2])) {
$return[$data[1]] = $data[2];
}
}
} # Items
else {
# Browsing each line
foreach ($lines as $line) {
$data = preg_split('/ /', $line);
if (isset($data[1])) {
$return[$data[1]] = array(substr($data[2], 1), $data[4]);
}
}
}
return $return;
}
/**
* Send stats command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function stats($server, $port)
{
# Executing command
if (($return = $this->exec('stats', $server, $port))) {
return $this->parse($return);
}
return false;
}
/**
* Send stats settings command to server
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function settings($server, $port)
{
# Executing command
if (($return = $this->exec('stats settings', $server, $port))) {
return $this->parse($return);
}
return false;
}
/**
* Send stats items command to server to retrieve slabs stats
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
*
* @return Array|Boolean
*/
public function slabs($server, $port)
{
# Initializing
$slabs = array();
# Finding uptime
$stats = $this->stats($server, $port);
$slabs['uptime'] = $stats['uptime'];
unset($stats);
# Executing command : slabs stats
if (($result = $this->exec('stats slabs', $server, $port))) {
# Parsing result
$result = $this->parse($result);
$slabs['active_slabs'] = $result['active_slabs'];
$slabs['total_malloced'] = $result['total_malloced'];
unset($result['active_slabs']);
unset($result['total_malloced']);
# Indexing by slabs
foreach ($result as $key => $value) {
$key = preg_split('/:/', $key);
$slabs[$key[0]][$key[1]] = $value;
}
# Executing command : items stats
if (($result = $this->exec('stats items', $server, $port))) {
# Parsing result
$result = $this->parse($result);
# Indexing by slabs
foreach ($result as $key => $value) {
$key = preg_split('/:/', $key);
$slabs[$key[1]]['items:' . $key[2]] = $value;
}
return $slabs;
}
}
return false;
}
/**
* Send stats cachedump command to server to retrieve slabs items
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Interger $slab Slab ID
*
* @return Array|Boolean
*/
public function items($server, $port, $slab)
{
# Initializing
$items = false;
# Executing command : stats cachedump
if (($result = $this->exec('stats cachedump ' . $slab . ' ' . self::$_ini->get('max_item_dump'), $server, $port))) {
# Parsing result
$items = $this->parse($result, false);
}
return $items;
}
/**
* Send get command to server to retrieve an item
* Return the result if successful or false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to retrieve
*
* @return String
*/
public function get($server, $port, $key)
{
# Executing command : get
if (($string = $this->exec('get ' . $key, $server, $port))) {
$string = preg_replace('/^VALUE ' . preg_quote($key, '/') . '[0-9 ]*\r\n/', '', $string);
if (ord($string[0]) == 0x78 && in_array(ord($string[1]), array(0x01, 0x5e, 0x9c, 0xda))) {
return gzuncompress($string);
}
return $string;
}
return self::$_log;
}
/**
* Set an item
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to store
* @param Mixed $data Data to store
* @param Integer $duration Duration
*
* @return String
*/
function set($server, $port, $key, $data, $duration)
{
# Formatting data
$data = preg_replace('/\r/', '', $data);
# Executing command : set
if (($result = $this->exec('set ' . $key . ' 0 ' . $duration . ' ' . strlen($data) . "\r\n" . $data, $server, $port))) {
return $result;
}
return self::$_log;
}
/**
* Delete an item
* Return true if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to delete
*
* @return String
*/
public function delete($server, $port, $key)
{
# Executing command : delete
if (($result = $this->exec('delete ' . $key, $server, $port))) {
return $result;
}
return self::$_log;
}
/**
* Increment the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to increment
* @param Integer $value Value to increment
*
* @return String
*/
function increment($server, $port, $key, $value)
{
# Executing command : increment
if (($result = $this->exec('incr ' . $key . ' ' . $value, $server, $port))) {
return $result;
}
return self::$_log;
}
/**
* Decrement the key by value
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to decrement
* @param Integer $value Value to decrement
*
* @return String
*/
function decrement($server, $port, $key, $value)
{
# Executing command : decrement
if (($result = $this->exec('decr ' . $key . ' ' . $value, $server, $port))) {
return $result;
}
return self::$_log;
}
/**
* Flush all items on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param Integer $delay Delay before flushing server
*
* @return String
*/
function flush_all($server, $port, $delay)
{
# Executing command : flush_all
if (($result = $this->exec('flush_all ' . $delay, $server, $port))) {
return $result;
}
return self::$_log;
}
/**
* Search for item
* Return all the items matching parameters if successful, false otherwise
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $key Key to search
* @param String $level Level of Detail
* @param String $more More action
*
* @return array
*/
function search($server, $port, $search, $level = false, $more = false)
{
$slabs = array();
$items = false;
# Executing command : stats
if (($level == 'full') && ($result = $this->exec('stats', $server, $port))) {
# Parsing result
$result = $this->parse($result);
$infinite = (isset($result['time'], $result['uptime'])) ? ($result['time'] - $result['uptime']) : 0;
}
# Executing command : slabs stats
if (($result = $this->exec('stats slabs', $server, $port))) {
# Parsing result
$result = $this->parse($result);
unset($result['active_slabs']);
unset($result['total_malloced']);
# Indexing by slabs
foreach ($result as $key => $value) {
$key = preg_split('/:/', $key);
$slabs[$key[0]] = true;
}
}
# Exploring each slabs
foreach ($slabs as $slab => $unused) {
# Executing command : stats cachedump
if (($result = $this->exec('stats cachedump ' . $slab . ' 0', $server, $port))) {
# Parsing result
preg_match_all('/^ITEM ((?:.*)' . preg_quote($search, '/') . '(?:.*)) \[([0-9]*) b; ([0-9]*) s\]\r\n/imU', $result, $matchs, PREG_SET_ORDER);
foreach ($matchs as $item) {
# Search & Delete
if ($more == 'delete') {
$items[] = $item[1] . ' : ' . $this->delete($server, $port, $item[1]);
# Basic search
} else {
# Detail level
if ($level == 'full') {
$items[] = $item[1] . ' : [' . trim(Library_Data_Analysis::byteResize($item[2])) . 'b, expire in ' . (($item[3] == $infinite) ? '&#8734;' : Library_Data_Analysis::uptime($item[3] - time(), true)) . ']';
} else {
$items[] = $item[1];
}
}
}
}
unset($slabs[$slab]);
}
if (is_array($items)) {
sort($items);
}
return $items;
}
/**
* Execute a telnet command on a server
* Return the result
*
* @param String $server Hostname
* @param Integer $port Hostname Port
* @param String $command Command to execute
*
* @return String
*/
function telnet($server, $port, $command)
{
# Executing command
if (($result = $this->exec($command, $server, $port))) {
return $result;
}
return self::$_log;
}
}

View File

@ -0,0 +1,186 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Configuration class for editing, saving, ...
*
* @author elijaa@free.fr
* @since 19/05/2010
*/
class Library_Configuration_Loader
{
# Singleton
protected static $_instance = null;
# Configuration file
protected static $_iniPath = './Config/Memcache.php';
# Configuration needed keys and default values
protected static $_iniKeys = array('stats_api' => 'Server',
'slabs_api' => 'Server',
'items_api' => 'Server',
'get_api' => 'Server',
'set_api' => 'Server',
'delete_api' => 'Server',
'flush_all_api' => 'Server',
'connection_timeout' => 1,
'max_item_dump' => 100,
'refresh_rate' => 2,
'memory_alert' => 80,
'hit_rate_alert' => 90,
'eviction_alert' => 0,
'file_path' => 'Temp/',
'servers' => array('Default' => array('127.0.0.1:11211' => array('hostname' => '127.0.0.1', 'port' => 11211))));
# Storage
protected static $_ini = array();
/**
* Constructor, load configuration file and parse server list
*
* @return Void
*/
protected function __construct()
{
# Checking ini File
if (file_exists(self::$_iniPath)) {
# Opening ini file
self::$_ini = require self::$_iniPath;
} else {
# Fallback
self::$_ini = self::$_iniKeys;
}
}
/**
* Get Library_Configuration_Loader singleton
*
* @return Library_Configuration_Loader
*/
public static function singleton()
{
if (! isset(self::$_instance)) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Config key to retrieve
* Return the value, or false if does not exists
*
* @param String $key Key to get
*
* @return Mixed
*/
public function get($key)
{
if (isset(self::$_ini[$key])) {
return self::$_ini[$key];
}
return false;
}
/**
* Servers to retrieve from cluster
* Return the value, or false if does not exists
*
* @param String $cluster Cluster to retreive
*
* @return Array
*/
public function cluster($cluster)
{
if (isset(self::$_ini['servers'][$cluster])) {
return self::$_ini['servers'][$cluster];
}
return array();
}
/**
* Check and return server data
* Return the value, or false if does not exists
*
* @param String $server Server to retreive
*
* @return Array
*/
public function server($server)
{
foreach (self::$_ini['servers'] as $cluster => $servers) {
if (isset(self::$_ini['servers'][$cluster][$server])) {
return self::$_ini['servers'][$cluster][$server];
}
}
return array();
}
/**
* Config key to set
*
* @param String $key Key to set
* @param Mixed $value Value to set
*
* @return Boolean
*/
public function set($key, $value)
{
self::$_ini[$key] = $value;
}
/**
* Return actual ini file path
*
* @return String
*/
public function path()
{
return self::$_iniPath;
}
/**
* Check if every ini keys are set
* Return true if ini is correct, false otherwise
*
* @return Boolean
*/
public function check()
{
# Checking configuration keys
foreach (array_keys(self::$_iniKeys) as $iniKey) {
# Ini file key not set
if (isset(self::$_ini[$iniKey]) === false) {
return false;
}
}
return true;
}
/**
* Write ini file
* Return true if written, false otherwise
*
* @return Boolean
*/
public function write()
{
if ($this->check()) {
return is_numeric(file_put_contents(self::$_iniPath, '<?php' . PHP_EOL . 'return ' . var_export(self::$_ini, true) . ';'));
}
return false;
}
}

View File

@ -0,0 +1,327 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Analysis of memcached command response
*
* @author elijaa@free.fr
* @since 20/03/2010
*/
class Library_Data_Analysis
{
private static $_non_additive = array(
'libevent',
'pid',
'pointer_size',
'time',
'uptime',
'version',
);
/**
* Merge two arrays of stats from Command_XX::stats()
*
* @param Array $array Statistic from Command_XX::stats()
* @param Array $stats Statistic from Command_XX::stats()
*
* @return Array
*/
public static function merge($array, $stats)
{
# Checking input
if (! is_array($array)) {
return $stats;
} elseif (! is_array($stats)) {
return $array;
}
# Merging Stats
foreach ($stats as $key => $value) {
if (! isset($array[$key]) || in_array($key, self::$_non_additive)) {
$array[$key] = $value;
} else {
$array[$key] += $value;
}
}
return $array;
}
/**
* Diff two arrays of stats from Command_XX::stats()
*
* @param Array $array Statistic from Command_XX::stats()
* @param Array $stats Statistic from Command_XX::stats()
*
* @return Array
*/
public static function diff($array, $stats)
{
# Checking input
if (! is_array($array)) {
return $stats;
} elseif (! is_array($stats)) {
return $array;
}
# Diff for each key
foreach ($stats as $key => $value) {
if (isset($array[$key]) && ! in_array($key, self::$_non_additive)) {
$stats[$key] = $value - $array[$key];
}
}
return $stats;
}
/**
* Analyse and return memcache stats command
*
* @param Array $stats Statistic from Command_XX::stats()
*
* @return Array
*/
public static function stats($stats)
{
if (! is_array($stats) || (count($stats) == 0)) {
return false;
}
# Command set()
$stats['set_rate'] = ($stats['cmd_set'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_set'] / $stats['uptime'], 1);
# Command get()
$stats['get_hits_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_hits'] / $stats['cmd_get'] * 100, 1);
$stats['get_misses_percent'] = ($stats['cmd_get'] == 0) ? ' - ' : sprintf('%.1f', $stats['get_misses'] / $stats['cmd_get'] * 100, 1);
$stats['get_rate'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_get'] / $stats['uptime'], 1);
# Command delete(), version > 1.2.X
if (isset($stats['delete_hits'], $stats['delete_misses'])) {
$stats['cmd_delete'] = $stats['delete_hits'] + $stats['delete_misses'];
$stats['delete_hits_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_hits'] / $stats['cmd_delete'] * 100, 1);
$stats['delete_misses_percent'] = ($stats['cmd_delete'] == 0) ? ' - ' : sprintf('%.1f', $stats['delete_misses'] / $stats['cmd_delete'] * 100, 1);
} else {
$stats['cmd_delete'] = 0;
$stats['delete_hits_percent'] = ' - ';
$stats['delete_misses_percent'] = ' - ';
}
$stats['delete_rate'] = ($stats['cmd_delete'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_delete'] / $stats['uptime'], 1);
# Command cas(), version > 1.2.X
if (isset($stats['cas_hits'], $stats['cas_misses'], $stats['cas_badval'])) {
$stats['cmd_cas'] = $stats['cas_hits'] + $stats['cas_misses'] + $stats['cas_badval'];
$stats['cas_hits_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_hits'] / $stats['cmd_cas'] * 100, 1);
$stats['cas_misses_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_misses'] / $stats['cmd_cas'] * 100, 1);
$stats['cas_badval_percent'] = ($stats['cmd_cas'] == 0) ? ' - ' : sprintf('%.1f', $stats['cas_badval'] / $stats['cmd_cas'] * 100, 1);
} else {
$stats['cmd_cas'] = 0;
$stats['cas_hits_percent'] = ' - ';
$stats['cas_misses_percent'] = ' - ';
$stats['cas_badval_percent'] = ' - ';
}
$stats['cas_rate'] = ($stats['cmd_cas'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_cas'] / $stats['uptime'], 1);
# Command increment(), version > 1.2.X
if (isset($stats['incr_hits'], $stats['incr_misses'])) {
$stats['cmd_incr'] = $stats['incr_hits'] + $stats['incr_misses'];
$stats['incr_hits_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_hits'] / $stats['cmd_incr'] * 100, 1);
$stats['incr_misses_percent'] = ($stats['cmd_incr'] == 0) ? ' - ' : sprintf('%.1f', $stats['incr_misses'] / $stats['cmd_incr'] * 100, 1);
} else {
$stats['cmd_incr'] = 0;
$stats['incr_hits_percent'] = ' - ';
$stats['incr_misses_percent'] = ' - ';
}
$stats['incr_rate'] = ($stats['cmd_incr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_incr'] / $stats['uptime'], 1);
# Command decrement(), version > 1.2.X
if (isset($stats['decr_hits'], $stats['decr_misses'])) {
$stats['cmd_decr'] = $stats['decr_hits'] + $stats['decr_misses'];
$stats['decr_hits_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_hits'] / $stats['cmd_decr'] * 100, 1);
$stats['decr_misses_percent'] = ($stats['cmd_decr'] == 0) ? ' - ' : sprintf('%.1f', $stats['decr_misses'] / $stats['cmd_decr'] * 100, 1);
} else {
$stats['cmd_decr'] = 0;
$stats['decr_hits_percent'] = ' - ';
$stats['decr_misses_percent'] = ' - ';
}
$stats['decr_rate'] = ($stats['cmd_decr'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_decr'] / $stats['uptime'], 1);
# Command decrement(), version > 1.4.7
if (isset($stats['touch_hits'], $stats['touch_misses'])) {
$stats['cmd_touch'] = $stats['touch_hits'] + $stats['touch_misses'];
$stats['touch_hits_percent'] = ($stats['cmd_touch'] == 0) ? ' - ' : sprintf('%.1f', $stats['touch_hits'] / $stats['cmd_touch'] * 100, 1);
$stats['touch_misses_percent'] = ($stats['cmd_touch'] == 0) ? ' - ' : sprintf('%.1f', $stats['touch_misses'] / $stats['cmd_touch'] * 100, 1);
} else {
$stats['cmd_touch'] = 0;
$stats['touch_hits_percent'] = ' - ';
$stats['touch_misses_percent'] = ' - ';
}
$stats['touch_rate'] = ($stats['cmd_touch'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_touch'] / $stats['uptime'], 1);
# Total hit & miss
#$stats['cmd_total'] = $stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr'];
#$stats['hit_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_hits']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1);
#$stats['miss_percent'] = ($stats['cmd_get'] == 0) ? '0.0' : sprintf('%.1f', ($stats['get_misses']) / ($stats['get_hits'] + $stats['get_misses']) * 100, 1);
# Command flush_all
if (isset($stats['cmd_flush'])) {
$stats['flush_rate'] = ($stats['cmd_flush'] == 0) ? '0.0' : sprintf('%.1f', $stats['cmd_flush'] / $stats['uptime'], 1);
} else {
$stats['flush_rate'] = '0.0';
}
# Cache size
$stats['bytes_percent'] = ($stats['limit_maxbytes'] == 0) ? '0.0' : sprintf('%.1f', $stats['bytes'] / $stats['limit_maxbytes'] * 100, 1);
# Request rate
$stats['request_rate'] = sprintf('%.1f', ($stats['cmd_get'] + $stats['cmd_set'] + $stats['cmd_delete'] + $stats['cmd_cas'] + $stats['cmd_incr'] + $stats['cmd_decr']) / $stats['uptime'], 1);
$stats['hit_rate'] = sprintf('%.1f', ($stats['get_hits']) / $stats['uptime'], 1);
$stats['miss_rate'] = sprintf('%.1f', ($stats['get_misses']) / $stats['uptime'], 1);
# Eviction & reclaimed rate
$stats['eviction_rate'] = ($stats['evictions'] == 0) ? '0.0' : sprintf('%.1f', $stats['evictions'] / $stats['uptime'], 1);
$stats['reclaimed_rate'] = (! isset($stats['reclaimed']) || ($stats['reclaimed'] == 0)) ? '0.0' : sprintf('%.1f', $stats['reclaimed'] / $stats['uptime'], 1);
return $stats;
}
/**
* Analyse and return memcache slabs command
*
* @param Array $slabs Statistic from Command_XX::slabs()
*
* @return Array
*/
public static function slabs($slabs)
{
# Initializing Used Slabs
$slabs['used_slabs'] = 0;
$slabs['total_wasted'] = 0;
# Request Rate par Slabs
foreach ($slabs as $id => $slab) {
# Check if it's a Slab
if (is_numeric($id)) {
# Check if Slab is used
if ($slab['used_chunks'] > 0) {
$slabs['used_slabs'] ++;
}
$slabs[$id]['request_rate'] = sprintf('%.1f', ($slab['get_hits'] + $slab['cmd_set'] + $slab['delete_hits'] + $slab['cas_hits'] + $slab['cas_badval'] + $slab['incr_hits'] + $slab['decr_hits']) / $slabs['uptime'], 1);
$slabs[$id]['mem_wasted'] = (($slab['total_chunks'] * $slab['chunk_size']) < $slab['mem_requested']) ? (($slab['total_chunks'] - $slab['used_chunks']) * $slab['chunk_size']) : (($slab['total_chunks'] * $slab['chunk_size']) - $slab['mem_requested']);
$slabs['total_wasted'] += $slabs[$id]['mem_wasted'];
}
}
# Cheking server total malloced > 0
if (! isset($slabs['total_malloced'])) {
$slabs['total_malloced'] = 0;
}
return $slabs;
}
/**
* Calculate Uptime
*
* @param Integer $uptime Uptime timestamp
* @param Boolean $compact Compact Mode
*
* @return String
*/
public static function uptime($uptime, $compact = false)
{
if ($uptime > 0) {
$days = floor($uptime / 60 / 60 / 24);
$hours = $uptime / 60 / 60 % 24;
$mins = $uptime / 60 % 60;
if (($days + $hours + $mins) == 0) {
return ' less than 1 min';
}
if ($compact == false) {
return $days . ' day' . (($days > 1) ? 's' : '') . ' ' . $hours . ' hr' . (($hours > 1) ? 's' : '') . ' ' . $mins . ' min' . (($mins > 1) ? 's' : '');
} else {
return $days . 'd ' . $hours . 'h ' . $mins . 'm';
}
}
return ' - ';
}
/**
* Resize a byte value
*
* @param Integer $value Value to resize
*
* @return String
*/
public static function byteResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach ($units as $unit) {
if ($value < 1024) {
break;
}
$value /= 1024;
}
return sprintf('%.1f %s', $value, $unit);
}
/**
* Resize a value
*
* @param Integer $value Value to resize
*
* @return String
*/
public static function valueResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach ($units as $unit) {
if ($value < 1000) {
break;
}
$value /= 1000;
}
return sprintf('%.1f%s', $value, $unit);
}
/**
* Resize a hit value
*
* @param Integer $value Hit value to resize
*
* @return String
*/
public static function hitResize($value)
{
# Unit list
$units = array('', 'K', 'M', 'G', 'T');
# Resizing
foreach ($units as $unit) {
if ($value < 10000000) {
break;
}
$value /= 1000;
}
return sprintf('%.0f%s', $value, $unit);
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Error container
*
* @author elijaa@free.fr
* @since 11/10/2010
*/
class Library_Data_Error
{
private static $_errors = array();
/**
* Add an error to the container
* Return true if successful, false otherwise
*
* @param String $error Error message
*
* @return Boolean
*/
public static function add($error)
{
return array_push(self::$_errors, $error);
}
/**
* Return last Error message
*
* @return Mixed
*/
public static function last()
{
return (isset(self::$_errors[count(self::$_errors) - 1])) ? self::$_errors[count(self::$_errors) - 1] : null;
}
/**
* Return errors count
*
* @return Integer
*/
public static function count()
{
return count(self::$_errors);
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Copyright 2011 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Version container
*
* @author cyrille.mahieux@free.fr
* @since 24/08/2011
*/
class Library_Data_Version
{
# Version file
protected static $_file = 'latest';
# Google Code latest version data file
protected static $_latest = 'https://blog.elijaa.org/public/latest';
# Time between HTTP check
protected static $_time = 1296000; # 15 days
/**
* Check for the latest version, from local cache or via http
* Return true if a newer version is available, false otherwise
*
* @return Boolean
*/
public static function check()
{
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Version definition file path
$path = rtrim($_ini->get('file_path'), '/') . DIRECTORY_SEPARATOR . self::$_file;
# Checking if path is writable
if (is_writable($_ini->get('file_path'))) {
# Checking if file was modified for less than 15 days ago
if ((is_array($stats = @stat($path))) && (isset($stats['mtime'])) && ($stats['mtime'] > (time() - self::$_time))) {
# Opening file and checking for latest version
return (version_compare(CURRENT_VERSION, file_get_contents($path)) == - 1);
} else {
# Getting last version from Google Code
if ($latest = @file_get_contents(self::$_latest)) {
# Saving latest version in file
file_put_contents($path, $latest);
# Checking for latest version
return (version_compare(CURRENT_VERSION, $latest) == - 1);
} else {
# To avoid error spam
file_put_contents($path, 'Net unreachable');
return true;
}
}
}
}
}

View File

@ -0,0 +1,143 @@
<?php
/**
* Copyright 2010 Cyrille Mahieux
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations
* under the License.
*
* ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°> ><)))°>
*
* Manipulation of HTML
*
* @author elijaa@free.fr
* @since 05/04/2010
*/
class Library_HTML_Components
{
/**
* Dump server list in an HTML select
*
* @return String
*/
public static function serverSelect($name, $selected = '', $class = '', $events = '')
{
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Select Name
$serverList = '<select id="' . $name . '" ';
# CSS Class
$serverList .= ($class != '') ? 'class="' . $class . '"' : '';
# Javascript Events
$serverList .= ' ' . $events . '>';
foreach ($_ini->get('servers') as $cluster => $servers) {
# Cluster
$serverList .= '<option value="' . $cluster . '" ';
$serverList .= ($selected == $cluster) ? 'selected="selected"' : '';
$serverList .= '>' . $cluster . ' cluster</option>';
# Cluster server
foreach ($servers as $name => $servers) {
$serverList .= '<option value="' . $name . '" ';
$serverList .= ($selected == $name) ? 'selected="selected"' : '';
$serverList .= '>&nbsp;&nbsp;-&nbsp;' . ((strlen($name) > 38) ? substr($name, 0, 38) . ' [...]' : $name) . '</option>';
}
}
return $serverList . '</select>';
}
/**
* Dump cluster list in an HTML select
*
* @return String
*/
public static function clusterSelect($name, $selected = '', $class = '', $events = '')
{
# Loading ini file
$_ini = Library_Configuration_Loader::singleton();
# Select Name
$clusterList = '<select id="' . $name . '" ';
# CSS Class
$clusterList .= ($class != '') ? 'class="' . $class . '"' : '';
# Javascript Events
$clusterList .= ' ' . $events . '>';
foreach ($_ini->get('servers') as $cluster => $servers) {
# Option value and selected case
$clusterList .= '<option value="' . $cluster . '" ';
$clusterList .= ($selected == $cluster) ? 'selected="selected"' : '';
$clusterList .= '>' . $cluster . ' cluster</option>';
}
return $clusterList . '</select>';
}
/**
* Dump server response in proper formatting
*
* @param String $hostname Hostname
* @param String $port Port
* @param Mixed $data Data (reponse)
*
* @return String
*/
public static function serverResponse($hostname, $port, $data)
{
$header = '<span class="red">Server ' . $hostname . ':' . $port . "</span>\r\n";
$return = '';
if (is_array($data)) {
foreach ($data as $string) {
$return .= $string . "\r\n";
}
return $header . htmlentities($return, ENT_NOQUOTES | 0, 'UTF-8') . "\r\n";
}
return $header . $return . $data . "\r\n";
}
/**
* Dump api list un HTML select with select name
*
* @param String $iniAPI API Name from ini file
* @param String $id Select ID
*
* @return String
*/
public static function apiList($iniAPI = '', $id)
{
return '<select id="' . $id . '" name="' . $id . '">
<option value="Server" ' . self::selected('Server', $iniAPI) . '>Server API</option>
<option value="Memcache" ' . self::selected('Memcache', $iniAPI) . '>Memcache API</option>
<option value="Memcached" ' . self::selected('Memcached', $iniAPI) . '>Memcached API</option>
</select>';
}
/**
* Used to see if an option is selected
*
* @param String $actual Actual value
* @param String $selected Selected value
*
* @return String
*/
private static function selected($actual, $selected)
{
if ($actual == $selected) {
return 'selected="selected"';
}
}
}

View File

@ -0,0 +1,391 @@
/*
Highcharts JS v5.0.9 (2017-03-08)
(c) 2009-2016 Torstein Honsi
License: www.highcharts.com/license
*/
(function(I,a){"object"===typeof module&&module.exports?module.exports=I.document?a(I):a:I.Highcharts=a(I)})("undefined"!==typeof window?window:this,function(I){I=function(){var a=window,B=a.document,z=a.navigator&&a.navigator.userAgent||"",C=B&&B.createElementNS&&!!B.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,E=/(edge|msie|trident)/i.test(z)&&!window.opera,u=!C,h=/Firefox/.test(z),n=h&&4>parseInt(z.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16,!0):{product:"Highcharts",
version:"5.0.9",deg2rad:2*Math.PI/360,doc:B,hasBidiBug:n,hasTouch:B&&void 0!==B.documentElement.ontouchstart,isMS:E,isWebKit:/AppleWebKit/.test(z),isFirefox:h,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(z),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:C,vml:u,win:a,charts:[],marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){}}}();(function(a){var B=[],z=a.charts,C=a.doc,E=a.win;a.error=function(u,h){u=a.isNumber(u)?"Highcharts error #"+
u+": www.highcharts.com/errors/"+u:u;if(h)throw Error(u);E.console&&console.log(u)};a.Fx=function(a,h,n){this.options=h;this.elem=a;this.prop=n};a.Fx.prototype={dSetter:function(){var a=this.paths[0],h=this.paths[1],n=[],t=this.now,l=a.length,k;if(1===t)n=this.toD;else if(l===h.length&&1>t)for(;l--;)k=parseFloat(a[l]),n[l]=isNaN(k)?a[l]:t*parseFloat(h[l]-k)+k;else n=h;this.elem.attr("d",n,null,!0)},update:function(){var a=this.elem,h=this.prop,n=this.now,t=this.options.step;if(this[h+"Setter"])this[h+
"Setter"]();else a.attr?a.element&&a.attr(h,n,null,!0):a.style[h]=n+this.unit;t&&t.call(a,n,this)},run:function(a,h,n){var u=this,l=function(a){return l.stopped?!1:u.step(a)},k;this.startTime=+new Date;this.start=a;this.end=h;this.unit=n;this.now=this.start;this.pos=0;l.elem=this.elem;l.prop=this.prop;l()&&1===B.push(l)&&(l.timerId=setInterval(function(){for(k=0;k<B.length;k++)B[k]()||B.splice(k--,1);B.length||clearInterval(l.timerId)},13))},step:function(a){var h=+new Date,u,t=this.options;u=this.elem;
var l=t.complete,k=t.duration,e=t.curAnim,c;if(u.attr&&!u.element)u=!1;else if(a||h>=k+this.startTime){this.now=this.end;this.pos=1;this.update();a=e[this.prop]=!0;for(c in e)!0!==e[c]&&(a=!1);a&&l&&l.call(u);u=!1}else this.pos=t.easing((h-this.startTime)/k),this.now=this.start+(this.end-this.start)*this.pos,this.update(),u=!0;return u},initPath:function(u,h,n){function t(a){var b,f;for(r=a.length;r--;)b="M"===a[r]||"L"===a[r],f=/[a-zA-Z]/.test(a[r+3]),b&&f&&a.splice(r+1,0,a[r+1],a[r+2],a[r+1],a[r+
2])}function l(a,f){for(;a.length<m;){a[0]=f[m-a.length];var d=a.slice(0,b);[].splice.apply(a,[0,0].concat(d));A&&(d=a.slice(a.length-b),[].splice.apply(a,[a.length,0].concat(d)),r--)}a[0]="M"}function k(a,f){for(var c=(m-a.length)/b;0<c&&c--;)d=a.slice().splice(a.length/v-b,b*v),d[0]=f[m-b-c*b],H&&(d[b-6]=d[b-2],d[b-5]=d[b-1]),[].splice.apply(a,[a.length/v,0].concat(d)),A&&c--}h=h||"";var e,c=u.startX,p=u.endX,H=-1<h.indexOf("C"),b=H?7:3,m,d,r;h=h.split(" ");n=n.slice();var A=u.isArea,v=A?2:1,f;
H&&(t(h),t(n));if(c&&p){for(r=0;r<c.length;r++)if(c[r]===p[0]){e=r;break}else if(c[0]===p[p.length-c.length+r]){e=r;f=!0;break}void 0===e&&(h=[])}h.length&&a.isNumber(e)&&(m=n.length+e*v*b,f?(l(h,n),k(n,h)):(l(n,h),k(h,n)));return[h,n]}};a.extend=function(a,h){var u;a||(a={});for(u in h)a[u]=h[u];return a};a.merge=function(){var u,h=arguments,n,t={},l=function(k,e){var c,p;"object"!==typeof k&&(k={});for(p in e)e.hasOwnProperty(p)&&(c=e[p],a.isObject(c,!0)&&"renderTo"!==p&&"number"!==typeof c.nodeType?
k[p]=l(k[p]||{},c):k[p]=e[p]);return k};!0===h[0]&&(t=h[1],h=Array.prototype.slice.call(h,2));n=h.length;for(u=0;u<n;u++)t=l(t,h[u]);return t};a.pInt=function(a,h){return parseInt(a,h||10)};a.isString=function(a){return"string"===typeof a};a.isArray=function(a){a=Object.prototype.toString.call(a);return"[object Array]"===a||"[object Array Iterator]"===a};a.isObject=function(u,h){return u&&"object"===typeof u&&(!h||!a.isArray(u))};a.isNumber=function(a){return"number"===typeof a&&!isNaN(a)};a.erase=
function(a,h){for(var u=a.length;u--;)if(a[u]===h){a.splice(u,1);break}};a.defined=function(a){return void 0!==a&&null!==a};a.attr=function(u,h,n){var t,l;if(a.isString(h))a.defined(n)?u.setAttribute(h,n):u&&u.getAttribute&&(l=u.getAttribute(h));else if(a.defined(h)&&a.isObject(h))for(t in h)u.setAttribute(t,h[t]);return l};a.splat=function(u){return a.isArray(u)?u:[u]};a.syncTimeout=function(a,h,n){if(h)return setTimeout(a,h,n);a.call(0,n)};a.pick=function(){var a=arguments,h,n,t=a.length;for(h=
0;h<t;h++)if(n=a[h],void 0!==n&&null!==n)return n};a.css=function(u,h){a.isMS&&!a.svg&&h&&void 0!==h.opacity&&(h.filter="alpha(opacity\x3d"+100*h.opacity+")");a.extend(u.style,h)};a.createElement=function(u,h,n,t,l){u=C.createElement(u);var k=a.css;h&&a.extend(u,h);l&&k(u,{padding:0,border:"none",margin:0});n&&k(u,n);t&&t.appendChild(u);return u};a.extendClass=function(u,h){var n=function(){};n.prototype=new u;a.extend(n.prototype,h);return n};a.pad=function(a,h,n){return Array((h||2)+1-String(a).length).join(n||
0)+a};a.relativeLength=function(a,h){return/%$/.test(a)?h*parseFloat(a)/100:parseFloat(a)};a.wrap=function(a,h,n){var t=a[h];a[h]=function(){var a=Array.prototype.slice.call(arguments),k=arguments,e=this;e.proceed=function(){t.apply(e,arguments.length?arguments:k)};a.unshift(t);a=n.apply(this,a);e.proceed=null;return a}};a.getTZOffset=function(u){var h=a.Date;return 6E4*(h.hcGetTimezoneOffset&&h.hcGetTimezoneOffset(u)||h.hcTimezoneOffset||0)};a.dateFormat=function(u,h,n){if(!a.defined(h)||isNaN(h))return a.defaultOptions.lang.invalidDate||
"";u=a.pick(u,"%Y-%m-%d %H:%M:%S");var t=a.Date,l=new t(h-a.getTZOffset(h)),k,e=l[t.hcGetHours](),c=l[t.hcGetDay](),p=l[t.hcGetDate](),H=l[t.hcGetMonth](),b=l[t.hcGetFullYear](),m=a.defaultOptions.lang,d=m.weekdays,r=m.shortWeekdays,A=a.pad,t=a.extend({a:r?r[c]:d[c].substr(0,3),A:d[c],d:A(p),e:A(p,2," "),w:c,b:m.shortMonths[H],B:m.months[H],m:A(H+1),y:b.toString().substr(2,2),Y:b,H:A(e),k:e,I:A(e%12||12),l:e%12||12,M:A(l[t.hcGetMinutes]()),p:12>e?"AM":"PM",P:12>e?"am":"pm",S:A(l.getSeconds()),L:A(Math.round(h%
1E3),3)},a.dateFormats);for(k in t)for(;-1!==u.indexOf("%"+k);)u=u.replace("%"+k,"function"===typeof t[k]?t[k](h):t[k]);return n?u.substr(0,1).toUpperCase()+u.substr(1):u};a.formatSingle=function(u,h){var n=/\.([0-9])/,t=a.defaultOptions.lang;/f$/.test(u)?(n=(n=u.match(n))?n[1]:-1,null!==h&&(h=a.numberFormat(h,n,t.decimalPoint,-1<u.indexOf(",")?t.thousandsSep:""))):h=a.dateFormat(u,h);return h};a.format=function(u,h){for(var n="{",t=!1,l,k,e,c,p=[],H;u;){n=u.indexOf(n);if(-1===n)break;l=u.slice(0,
n);if(t){l=l.split(":");k=l.shift().split(".");c=k.length;H=h;for(e=0;e<c;e++)H=H[k[e]];l.length&&(H=a.formatSingle(l.join(":"),H));p.push(H)}else p.push(l);u=u.slice(n+1);n=(t=!t)?"}":"{"}p.push(u);return p.join("")};a.getMagnitude=function(a){return Math.pow(10,Math.floor(Math.log(a)/Math.LN10))};a.normalizeTickInterval=function(u,h,n,t,l){var k,e=u;n=a.pick(n,1);k=u/n;h||(h=l?[1,1.2,1.5,2,2.5,3,4,5,6,8,10]:[1,2,2.5,5,10],!1===t&&(1===n?h=a.grep(h,function(a){return 0===a%1}):.1>=n&&(h=[1/n])));
for(t=0;t<h.length&&!(e=h[t],l&&e*n>=u||!l&&k<=(h[t]+(h[t+1]||h[t]))/2);t++);return e=a.correctFloat(e*n,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,h){var n=a.length,t,l;for(l=0;l<n;l++)a[l].safeI=l;a.sort(function(a,e){t=h(a,e);return 0===t?a.safeI-e.safeI:t});for(l=0;l<n;l++)delete a[l].safeI};a.arrayMin=function(a){for(var h=a.length,n=a[0];h--;)a[h]<n&&(n=a[h]);return n};a.arrayMax=function(a){for(var h=a.length,n=a[0];h--;)a[h]>n&&(n=a[h]);return n};a.destroyObjectProperties=
function(a,h){for(var n in a)a[n]&&a[n]!==h&&a[n].destroy&&a[n].destroy(),delete a[n]};a.discardElement=function(u){var h=a.garbageBin;h||(h=a.createElement("div"));u&&h.appendChild(u);h.innerHTML=""};a.correctFloat=function(a,h){return parseFloat(a.toPrecision(h||14))};a.setAnimation=function(u,h){h.renderer.globalAnimation=a.pick(u,h.options.chart.animation,!0)};a.animObject=function(u){return a.isObject(u)?a.merge(u):{duration:u?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,
day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(u,h,n,t){u=+u||0;h=+h;var l=a.defaultOptions.lang,k=(u.toString().split(".")[1]||"").length,e,c;-1===h?h=Math.min(k,20):a.isNumber(h)||(h=2);c=(Math.abs(u)+Math.pow(10,-Math.max(h,k)-1)).toFixed(h);k=String(a.pInt(c));e=3<k.length?k.length%3:0;n=a.pick(n,l.decimalPoint);t=a.pick(t,l.thousandsSep);u=(0>u?"-":"")+(e?k.substr(0,e)+t:"");u+=k.substr(e).replace(/(\d{3})(?=\d)/g,"$1"+t);h&&(u+=n+c.slice(-h));return u};Math.easeInOutSine=
function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(u,h){return"width"===h?Math.min(u.offsetWidth,u.scrollWidth)-a.getStyle(u,"padding-left")-a.getStyle(u,"padding-right"):"height"===h?Math.min(u.offsetHeight,u.scrollHeight)-a.getStyle(u,"padding-top")-a.getStyle(u,"padding-bottom"):(u=E.getComputedStyle(u,void 0))&&a.pInt(u.getPropertyValue(h))};a.inArray=function(a,h){return h.indexOf?h.indexOf(a):[].indexOf.call(h,a)};a.grep=function(a,h){return[].filter.call(a,h)};a.find=function(a,
h){return[].find.call(a,h)};a.map=function(a,h){for(var n=[],t=0,l=a.length;t<l;t++)n[t]=h.call(a[t],a[t],t,a);return n};a.offset=function(a){var h=C.documentElement;a=a.getBoundingClientRect();return{top:a.top+(E.pageYOffset||h.scrollTop)-(h.clientTop||0),left:a.left+(E.pageXOffset||h.scrollLeft)-(h.clientLeft||0)}};a.stop=function(a,h){for(var n=B.length;n--;)B[n].elem!==a||h&&h!==B[n].prop||(B[n].stopped=!0)};a.each=function(a,h,n){return Array.prototype.forEach.call(a,h,n)};a.addEvent=function(u,
h,n){function t(a){a.target=a.srcElement||E;n.call(u,a)}var l=u.hcEvents=u.hcEvents||{};u.addEventListener?u.addEventListener(h,n,!1):u.attachEvent&&(u.hcEventsIE||(u.hcEventsIE={}),u.hcEventsIE[n.toString()]=t,u.attachEvent("on"+h,t));l[h]||(l[h]=[]);l[h].push(n);return function(){a.removeEvent(u,h,n)}};a.removeEvent=function(u,h,n){function t(a,c){u.removeEventListener?u.removeEventListener(a,c,!1):u.attachEvent&&(c=u.hcEventsIE[c.toString()],u.detachEvent("on"+a,c))}function l(){var a,c;if(u.nodeName)for(c in h?
(a={},a[h]=!0):a=e,a)if(e[c])for(a=e[c].length;a--;)t(c,e[c][a])}var k,e=u.hcEvents,c;e&&(h?(k=e[h]||[],n?(c=a.inArray(n,k),-1<c&&(k.splice(c,1),e[h]=k),t(h,n)):(l(),e[h]=[])):(l(),u.hcEvents={}))};a.fireEvent=function(u,h,n,t){var l;l=u.hcEvents;var k,e;n=n||{};if(C.createEvent&&(u.dispatchEvent||u.fireEvent))l=C.createEvent("Events"),l.initEvent(h,!0,!0),a.extend(l,n),u.dispatchEvent?u.dispatchEvent(l):u.fireEvent(h,l);else if(l)for(l=l[h]||[],k=l.length,n.target||a.extend(n,{preventDefault:function(){n.defaultPrevented=
!0},target:u,type:h}),h=0;h<k;h++)(e=l[h])&&!1===e.call(u,n)&&n.preventDefault();t&&!n.defaultPrevented&&t(n)};a.animate=function(u,h,n){var t,l="",k,e,c;a.isObject(n)||(t=arguments,n={duration:t[2],easing:t[3],complete:t[4]});a.isNumber(n.duration)||(n.duration=400);n.easing="function"===typeof n.easing?n.easing:Math[n.easing]||Math.easeInOutSine;n.curAnim=a.merge(h);for(c in h)a.stop(u,c),e=new a.Fx(u,n,c),k=null,"d"===c?(e.paths=e.initPath(u,u.d,h.d),e.toD=h.d,t=0,k=1):u.attr?t=u.attr(c):(t=parseFloat(a.getStyle(u,
c))||0,"opacity"!==c&&(l="px")),k||(k=h[c]),k&&k.match&&k.match("px")&&(k=k.replace(/px/g,"")),e.run(t,k,l)};a.seriesType=function(u,h,n,t,l){var k=a.getOptions(),e=a.seriesTypes;k.plotOptions[u]=a.merge(k.plotOptions[h],n);e[u]=a.extendClass(e[h]||function(){},t);e[u].prototype.type=u;l&&(e[u].prototype.pointClass=a.extendClass(a.Point,l));return e[u]};a.uniqueKey=function(){var a=Math.random().toString(36).substring(2,9),h=0;return function(){return"highcharts-"+a+"-"+h++}}();E.jQuery&&(E.jQuery.fn.highcharts=
function(){var u=[].slice.call(arguments);if(this[0])return u[0]?(new (a[a.isString(u[0])?u.shift():"Chart"])(this[0],u[0],u[1]),this):z[a.attr(this[0],"data-highcharts-chart")]});C&&!C.defaultView&&(a.getStyle=function(u,h){var n={width:"clientWidth",height:"clientHeight"}[h];if(u.style[h])return a.pInt(u.style[h]);"opacity"===h&&(h="filter");if(n)return u.style.zoom=1,Math.max(u[n]-2*a.getStyle(u,"padding"),0);u=u.currentStyle[h.replace(/\-(\w)/g,function(a,l){return l.toUpperCase()})];"filter"===
h&&(u=u.replace(/alpha\(opacity=([0-9]+)\)/,function(a,l){return l/100}));return""===u?1:a.pInt(u)});Array.prototype.forEach||(a.each=function(a,h,n){for(var t=0,l=a.length;t<l;t++)if(!1===h.call(n,a[t],t,a))return t});Array.prototype.indexOf||(a.inArray=function(a,h){var n,t=0;if(h)for(n=h.length;t<n;t++)if(h[t]===a)return t;return-1});Array.prototype.filter||(a.grep=function(a,h){for(var n=[],t=0,l=a.length;t<l;t++)h(a[t],t)&&n.push(a[t]);return n});Array.prototype.find||(a.find=function(a,h){var n,
t=a.length;for(n=0;n<t;n++)if(h(a[n],n))return a[n]})})(I);(function(a){var B=a.each,z=a.isNumber,C=a.map,E=a.merge,u=a.pInt;a.Color=function(h){if(!(this instanceof a.Color))return new a.Color(h);this.init(h)};a.Color.prototype={parsers:[{regex:/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,parse:function(a){return[u(a[1]),u(a[2]),u(a[3]),parseFloat(a[4],10)]}},{regex:/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,parse:function(a){return[u(a[1]),
u(a[2]),u(a[3]),1]}}],names:{white:"#ffffff",black:"#000000"},init:function(h){var n,t,l,k;if((this.input=h=this.names[h]||h)&&h.stops)this.stops=C(h.stops,function(e){return new a.Color(e[1])});else if(h&&"#"===h[0]&&(n=h.length,h=parseInt(h.substr(1),16),7===n?t=[(h&16711680)>>16,(h&65280)>>8,h&255,1]:4===n&&(t=[(h&3840)>>4|(h&3840)>>8,(h&240)>>4|h&240,(h&15)<<4|h&15,1])),!t)for(l=this.parsers.length;l--&&!t;)k=this.parsers[l],(n=k.regex.exec(h))&&(t=k.parse(n));this.rgba=t||[]},get:function(a){var h=
this.input,t=this.rgba,l;this.stops?(l=E(h),l.stops=[].concat(l.stops),B(this.stops,function(k,e){l.stops[e]=[l.stops[e][0],k.get(a)]})):l=t&&z(t[0])?"rgb"===a||!a&&1===t[3]?"rgb("+t[0]+","+t[1]+","+t[2]+")":"a"===a?t[3]:"rgba("+t.join(",")+")":h;return l},brighten:function(a){var h,t=this.rgba;if(this.stops)B(this.stops,function(l){l.brighten(a)});else if(z(a)&&0!==a)for(h=0;3>h;h++)t[h]+=u(255*a),0>t[h]&&(t[h]=0),255<t[h]&&(t[h]=255);return this},setOpacity:function(a){this.rgba[3]=a;return this}};
a.color=function(h){return new a.Color(h)}})(I);(function(a){var B,z,C=a.addEvent,E=a.animate,u=a.attr,h=a.charts,n=a.color,t=a.css,l=a.createElement,k=a.defined,e=a.deg2rad,c=a.destroyObjectProperties,p=a.doc,H=a.each,b=a.extend,m=a.erase,d=a.grep,r=a.hasTouch,A=a.inArray,v=a.isArray,f=a.isFirefox,y=a.isMS,G=a.isObject,F=a.isString,q=a.isWebKit,x=a.merge,J=a.noop,K=a.pick,L=a.pInt,g=a.removeEvent,D=a.stop,S=a.svg,M=a.SVG_NS,R=a.symbolSizes,N=a.win;B=a.SVGElement=function(){return this};B.prototype=
{opacity:1,SVG_NS:M,textProps:"direction fontSize fontWeight fontFamily fontStyle color lineHeight width textAlign textDecoration textOverflow textOutline".split(" "),init:function(a,g){this.element="span"===g?l(g):p.createElementNS(this.SVG_NS,g);this.renderer=a},animate:function(w,g,b){g=a.animObject(K(g,this.renderer.globalAnimation,!0));0!==g.duration?(b&&(g.complete=b),E(this,w,g)):(this.attr(w,null,b),g.step&&g.step.call(this));return this},colorGradient:function(w,g,b){var f=this.renderer,
d,c,q,D,O,y,r,G,e,m,p,l=[],Q;w.linearGradient?c="linearGradient":w.radialGradient&&(c="radialGradient");if(c){q=w[c];O=f.gradients;r=w.stops;m=b.radialReference;v(q)&&(w[c]=q={x1:q[0],y1:q[1],x2:q[2],y2:q[3],gradientUnits:"userSpaceOnUse"});"radialGradient"===c&&m&&!k(q.gradientUnits)&&(D=q,q=x(q,f.getRadialAttr(m,D),{gradientUnits:"userSpaceOnUse"}));for(p in q)"id"!==p&&l.push(p,q[p]);for(p in r)l.push(r[p]);l=l.join(",");O[l]?m=O[l].attr("id"):(q.id=m=a.uniqueKey(),O[l]=y=f.createElement(c).attr(q).add(f.defs),
y.radAttr=D,y.stops=[],H(r,function(w){0===w[1].indexOf("rgba")?(d=a.color(w[1]),G=d.get("rgb"),e=d.get("a")):(G=w[1],e=1);w=f.createElement("stop").attr({offset:w[0],"stop-color":G,"stop-opacity":e}).add(y);y.stops.push(w)}));Q="url("+f.url+"#"+m+")";b.setAttribute(g,Q);b.gradient=l;w.toString=function(){return Q}}},applyTextOutline:function(a){var w=this.element,g,b,f,d;-1!==a.indexOf("contrast")&&(a=a.replace(/contrast/g,this.renderer.getContrast(w.style.fill)));this.fakeTS=!0;this.ySetter=this.xSetter;
g=[].slice.call(w.getElementsByTagName("tspan"));a=a.split(" ");b=a[a.length-1];(f=a[0])&&"none"!==f&&(f=f.replace(/(^[\d\.]+)(.*?)$/g,function(a,w,g){return 2*w+g}),H(g,function(a){"highcharts-text-outline"===a.getAttribute("class")&&m(g,w.removeChild(a))}),d=w.firstChild,H(g,function(a,g){0===g&&(a.setAttribute("x",w.getAttribute("x")),g=w.getAttribute("y"),a.setAttribute("y",g||0),null===g&&w.setAttribute("y",0));a=a.cloneNode(1);u(a,{"class":"highcharts-text-outline",fill:b,stroke:b,"stroke-width":f,
"stroke-linejoin":"round"});w.insertBefore(a,d)}))},attr:function(a,g,b,f){var w,d=this.element,q,c=this,y;"string"===typeof a&&void 0!==g&&(w=a,a={},a[w]=g);if("string"===typeof a)c=(this[a+"Getter"]||this._defaultGetter).call(this,a,d);else{for(w in a)g=a[w],y=!1,f||D(this,w),this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(w)&&(q||(this.symbolAttr(a),q=!0),y=!0),!this.rotation||"x"!==w&&"y"!==w||(this.doTransform=!0),y||(y=this[w+"Setter"]||this._defaultSetter,y.call(this,
g,w,d),this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(w)&&this.updateShadows(w,g,y));this.doTransform&&(this.updateTransform(),this.doTransform=!1)}b&&b();return c},updateShadows:function(a,g,b){for(var w=this.shadows,f=w.length;f--;)b.call(w[f],"height"===a?Math.max(g-(w[f].cutHeight||0),0):"d"===a?this.d:g,a,w[f])},addClass:function(a,g){var w=this.attr("class")||"";-1===w.indexOf(a)&&(g||(a=(w+(w?" ":"")+a).replace(" "," ")),this.attr("class",a));return this},hasClass:function(a){return-1!==
u(this.element,"class").indexOf(a)},removeClass:function(a){u(this.element,"class",(u(this.element,"class")||"").replace(a,""));return this},symbolAttr:function(a){var w=this;H("x y r start end width height innerR anchorX anchorY".split(" "),function(g){w[g]=K(a[g],w[g])});w.attr({d:w.renderer.symbols[w.symbolName](w.x,w.y,w.width,w.height,w)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":"none")},crisp:function(a,g){var w,f={},b;g=g||a.strokeWidth||0;b=Math.round(g)%
2/2;a.x=Math.floor(a.x||this.x||0)+b;a.y=Math.floor(a.y||this.y||0)+b;a.width=Math.floor((a.width||this.width||0)-2*b);a.height=Math.floor((a.height||this.height||0)-2*b);k(a.strokeWidth)&&(a.strokeWidth=g);for(w in a)this[w]!==a[w]&&(this[w]=f[w]=a[w]);return f},css:function(a){var w=this.styles,g={},f=this.element,d,q="",c=!w,D=["textOverflow","width"];a&&a.color&&(a.fill=a.color);if(w)for(d in a)a[d]!==w[d]&&(g[d]=a[d],c=!0);if(c){w&&(a=b(w,g));w=this.textWidth=a&&a.width&&"auto"!==a.width&&"text"===
f.nodeName.toLowerCase()&&L(a.width);this.styles=a;w&&!S&&this.renderer.forExport&&delete a.width;if(y&&!S)t(this.element,a);else{w=function(a,w){return"-"+w.toLowerCase()};for(d in a)-1===A(d,D)&&(q+=d.replace(/([A-Z])/g,w)+":"+a[d]+";");q&&u(f,"style",q)}this.added&&("text"===this.element.nodeName&&this.renderer.buildText(this),a&&a.textOutline&&this.applyTextOutline(a.textOutline))}return this},strokeWidth:function(){return this["stroke-width"]||0},on:function(a,g){var w=this,f=w.element;r&&"click"===
a?(f.ontouchstart=function(a){w.touchEventFired=Date.now();a.preventDefault();g.call(f,a)},f.onclick=function(a){(-1===N.navigator.userAgent.indexOf("Android")||1100<Date.now()-(w.touchEventFired||0))&&g.call(f,a)}):f["on"+a]=g;return this},setRadialReference:function(a){var w=this.renderer.gradients[this.element.gradient];this.element.radialReference=a;w&&w.radAttr&&w.animate(this.renderer.getRadialAttr(a,w.radAttr));return this},translate:function(a,g){return this.attr({translateX:a,translateY:g})},
invert:function(a){this.inverted=a;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,g=this.translateY||0,f=this.scaleX,b=this.scaleY,d=this.inverted,q=this.rotation,c=this.element;d&&(a+=this.width,g+=this.height);a=["translate("+a+","+g+")"];d?a.push("rotate(90) scale(-1,1)"):q&&a.push("rotate("+q+" "+(c.getAttribute("x")||0)+" "+(c.getAttribute("y")||0)+")");(k(f)||k(b))&&a.push("scale("+K(f,1)+" "+K(b,1)+")");a.length&&c.setAttribute("transform",a.join(" "))},
toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,g,f){var w,b,d,q,c={};b=this.renderer;d=b.alignedObjects;var D,y;if(a){if(this.alignOptions=a,this.alignByTranslate=g,!f||F(f))this.alignTo=w=f||"renderer",m(d,this),d.push(this),f=null}else a=this.alignOptions,g=this.alignByTranslate,w=this.alignTo;f=K(f,b[w],b);w=a.align;b=a.verticalAlign;d=(f.x||0)+(a.x||0);q=(f.y||0)+(a.y||0);"right"===w?D=1:"center"===w&&(D=2);D&&(d+=(f.width-(a.width||0))/D);c[g?
"translateX":"x"]=Math.round(d);"bottom"===b?y=1:"middle"===b&&(y=2);y&&(q+=(f.height-(a.height||0))/y);c[g?"translateY":"y"]=Math.round(q);this[this.placed?"animate":"attr"](c);this.placed=!0;this.alignAttr=c;return this},getBBox:function(a,g){var w,f=this.renderer,d,q=this.element,c=this.styles,D,y=this.textStr,x,r=f.cache,G=f.cacheKeys,m;g=K(g,this.rotation);d=g*e;D=c&&c.fontSize;void 0!==y&&(m=y.toString(),-1===m.indexOf("\x3c")&&(m=m.replace(/[0-9]/g,"0")),m+=["",g||0,D,c&&c.width,c&&c.textOverflow].join());
m&&!a&&(w=r[m]);if(!w){if(q.namespaceURI===this.SVG_NS||f.forExport){try{(x=this.fakeTS&&function(a){H(q.querySelectorAll(".highcharts-text-outline"),function(w){w.style.display=a})})&&x("none"),w=q.getBBox?b({},q.getBBox()):{width:q.offsetWidth,height:q.offsetHeight},x&&x("")}catch(X){}if(!w||0>w.width)w={width:0,height:0}}else w=this.htmlGetBBox();f.isSVG&&(a=w.width,f=w.height,c&&"11px"===c.fontSize&&17===Math.round(f)&&(w.height=f=14),g&&(w.width=Math.abs(f*Math.sin(d))+Math.abs(a*Math.cos(d)),
w.height=Math.abs(f*Math.cos(d))+Math.abs(a*Math.sin(d))));if(m&&0<w.height){for(;250<G.length;)delete r[G.shift()];r[m]||G.push(m);r[m]=w}}return w},show:function(a){return this.attr({visibility:a?"inherit":"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var w=this;w.animate({opacity:0},{duration:a||150,complete:function(){w.attr({y:-9999})}})},add:function(a){var w=this.renderer,g=this.element,f;a&&(this.parentGroup=a);this.parentInverted=a&&a.inverted;
void 0!==this.textStr&&w.buildText(this);this.added=!0;if(!a||a.handleZ||this.zIndex)f=this.zIndexSetter();f||(a?a.element:w.box).appendChild(g);if(this.onAdd)this.onAdd();return this},safeRemoveChild:function(a){var w=a.parentNode;w&&w.removeChild(a)},destroy:function(){var a=this.element||{},g=this.renderer.isSVG&&"SPAN"===a.nodeName&&this.parentGroup,f,b;a.onclick=a.onmouseout=a.onmouseover=a.onmousemove=a.point=null;D(this);this.clipPath&&(this.clipPath=this.clipPath.destroy());if(this.stops){for(b=
0;b<this.stops.length;b++)this.stops[b]=this.stops[b].destroy();this.stops=null}this.safeRemoveChild(a);for(this.destroyShadows();g&&g.div&&0===g.div.childNodes.length;)a=g.parentGroup,this.safeRemoveChild(g.div),delete g.div,g=a;this.alignTo&&m(this.renderer.alignedObjects,this);for(f in this)delete this[f];return null},shadow:function(a,g,f){var w=[],b,d,c=this.element,q,D,y,x;if(!a)this.destroyShadows();else if(!this.shadows){D=K(a.width,3);y=(a.opacity||.15)/D;x=this.parentInverted?"(-1,-1)":
"("+K(a.offsetX,1)+", "+K(a.offsetY,1)+")";for(b=1;b<=D;b++)d=c.cloneNode(0),q=2*D+1-2*b,u(d,{isShadow:"true",stroke:a.color||"#000000","stroke-opacity":y*b,"stroke-width":q,transform:"translate"+x,fill:"none"}),f&&(u(d,"height",Math.max(u(d,"height")-q,0)),d.cutHeight=q),g?g.element.appendChild(d):c.parentNode.insertBefore(d,c),w.push(d);this.shadows=w}return this},destroyShadows:function(){H(this.shadows||[],function(a){this.safeRemoveChild(a)},this);this.shadows=void 0},xGetter:function(a){"circle"===
this.element.nodeName&&("x"===a?a="cx":"y"===a&&(a="cy"));return this._defaultGetter(a)},_defaultGetter:function(a){a=K(this[a],this.element?this.element.getAttribute(a):null,0);/^[\-0-9\.]+$/.test(a)&&(a=parseFloat(a));return a},dSetter:function(a,g,f){a&&a.join&&(a=a.join(" "));/(NaN| {2}|^$)/.test(a)&&(a="M 0 0");f.setAttribute(g,a);this[g]=a},dashstyleSetter:function(a){var w,g=this["stroke-width"];"inherit"===g&&(g=1);if(a=a&&a.toLowerCase()){a=a.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot",
"3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(w=a.length;w--;)a[w]=L(a[w])*g;a=a.join(",").replace(/NaN/g,"none");this.element.setAttribute("stroke-dasharray",a)}},alignSetter:function(a){this.element.setAttribute("text-anchor",{left:"start",center:"middle",right:"end"}[a])},opacitySetter:function(a,g,f){this[g]=a;f.setAttribute(g,a)},titleSetter:function(a){var w=this.element.getElementsByTagName("title")[0];
w||(w=p.createElementNS(this.SVG_NS,"title"),this.element.appendChild(w));w.firstChild&&w.removeChild(w.firstChild);w.appendChild(p.createTextNode(String(K(a),"").replace(/<[^>]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,f){"string"===typeof a?f.setAttribute(g,a):a&&this.colorGradient(a,g,f)},visibilitySetter:function(a,g,f){"inherit"===a?f.removeAttribute(g):f.setAttribute(g,a)},zIndexSetter:function(a,
g){var w=this.renderer,f=this.parentGroup,b=(f||w).element||w.box,d,c=this.element,q;d=this.added;var D;k(a)&&(c.zIndex=a,a=+a,this[g]===a&&(d=!1),this[g]=a);if(d){(a=this.zIndex)&&f&&(f.handleZ=!0);g=b.childNodes;for(D=0;D<g.length&&!q;D++)f=g[D],d=f.zIndex,f!==c&&(L(d)>a||!k(a)&&k(d)||0>a&&!k(d)&&b!==w.box)&&(b.insertBefore(c,f),q=!0);q||b.appendChild(c)}return q},_defaultSetter:function(a,g,f){f.setAttribute(g,a)}};B.prototype.yGetter=B.prototype.xGetter;B.prototype.translateXSetter=B.prototype.translateYSetter=
B.prototype.rotationSetter=B.prototype.verticalAlignSetter=B.prototype.scaleXSetter=B.prototype.scaleYSetter=function(a,g){this[g]=a;this.doTransform=!0};B.prototype["stroke-widthSetter"]=B.prototype.strokeSetter=function(a,g,f){this[g]=a;this.stroke&&this["stroke-width"]?(B.prototype.fillSetter.call(this,this.stroke,"stroke",f),f.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&&(f.removeAttribute("stroke"),this.hasStroke=!1)};z=a.SVGRenderer=
function(){this.init.apply(this,arguments)};z.prototype={Element:B,SVG_NS:M,init:function(a,g,b,d,c,D){var w;d=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(d));w=d.element;a.appendChild(w);-1===a.innerHTML.indexOf("xmlns")&&u(w,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=w;this.boxWrapper=d;this.alignedObjects=[];this.url=(f||q)&&p.getElementsByTagName("base").length?N.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,
"%20"):"";this.createElement("desc").add().element.appendChild(p.createTextNode("Created with Highcharts 5.0.9"));this.defs=this.createElement("defs").add();this.allowHTML=D;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var y;f&&a.getBoundingClientRect&&(g=function(){t(a,{left:0,top:0});y=a.getBoundingClientRect();t(a,{left:Math.ceil(y.left)-y.left+"px",top:Math.ceil(y.top)-y.top+"px"})},g(),this.unSubPixelFix=C(N,"resize",g))},getStyle:function(a){return this.style=
b({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();c(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy());this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;
g.init(this,a);return g},draw:J,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},buildText:function(a){var g=a.element,f=this,w=f.forExport,b=K(a.textStr,"").toString(),c=-1!==b.indexOf("\x3c"),q=g.childNodes,D,y,x,r,G=u(g,"x"),m=a.styles,e=a.textWidth,l=m&&m.lineHeight,v=m&&m.textOutline,k=m&&"ellipsis"===m.textOverflow,h=m&&"nowrap"===m.whiteSpace,F=m&&m.fontSize,A,J=q.length,m=e&&!a.added&&this.box,n=function(a){var w;w=/(px|em)$/.test(a&&a.style.fontSize)?
a.style.fontSize:F||f.style.fontSize||12;return l?L(l):f.fontMetrics(w,a.getAttribute("style")?a:g).h};A=[b,k,h,l,v,F,e].join();if(A!==a.textCache){for(a.textCache=A;J--;)g.removeChild(q[J]);c||v||k||e||-1!==b.indexOf(" ")?(D=/<.*class="([^"]+)".*>/,y=/<.*style="([^"]+)".*>/,x=/<.*href="(http[^"]+)".*>/,m&&m.appendChild(g),b=c?b.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(/<a/g,"\x3cspan").replace(/<\/(b|strong|i|em|a)>/g,
"\x3c/span\x3e").split(/<br.*?>/g):[b],b=d(b,function(a){return""!==a}),H(b,function(b,d){var c,q=0;b=b.replace(/^\s+|\s+$/g,"").replace(/<span/g,"|||\x3cspan").replace(/<\/span>/g,"\x3c/span\x3e|||");c=b.split("|||");H(c,function(b){if(""!==b||1===c.length){var m={},v=p.createElementNS(f.SVG_NS,"tspan"),l,F;D.test(b)&&(l=b.match(D)[1],u(v,"class",l));y.test(b)&&(F=b.match(y)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),u(v,"style",F));x.test(b)&&!w&&(u(v,"onclick",'location.href\x3d"'+b.match(x)[1]+
'"'),t(v,{cursor:"pointer"}));b=(b.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"\x3c").replace(/&gt;/g,"\x3e");if(" "!==b){v.appendChild(p.createTextNode(b));q?m.dx=0:d&&null!==G&&(m.x=G);u(v,m);g.appendChild(v);!q&&d&&(!S&&w&&t(v,{display:"block"}),u(v,"dy",n(v)));if(e){m=b.replace(/([^\^])-/g,"$1- ").split(" ");l=1<c.length||d||1<m.length&&!h;for(var A,H,O=[],J=n(v),K=a.rotation,L=b,P=L.length;(l||k)&&(m.length||O.length);)a.rotation=0,A=a.getBBox(!0),H=A.width,!S&&f.forExport&&(H=f.measureSpanWidth(v.firstChild.data,
a.styles)),A=H>e,void 0===r&&(r=A),k&&r?(P/=2,""===L||!A&&.5>P?m=[]:(L=b.substring(0,L.length+(A?-1:1)*Math.ceil(P)),m=[L+(3<e?"\u2026":"")],v.removeChild(v.firstChild))):A&&1!==m.length?(v.removeChild(v.firstChild),O.unshift(m.pop())):(m=O,O=[],m.length&&!h&&(v=p.createElementNS(M,"tspan"),u(v,{dy:J,x:G}),F&&u(v,"style",F),g.appendChild(v)),H>e&&(e=H)),m.length&&v.appendChild(p.createTextNode(m.join(" ").replace(/- /g,"-")));a.rotation=K}q++}}})}),r&&a.attr("title",a.textStr),m&&m.removeChild(g),
v&&a.applyTextOutline&&a.applyTextOutline(v)):g.appendChild(p.createTextNode(b.replace(/&lt;/g,"\x3c").replace(/&gt;/g,"\x3e")))}},getContrast:function(a){a=n(a).rgba;return 510<a[0]+a[1]+a[2]?"#000000":"#FFFFFF"},button:function(a,g,f,d,c,q,D,m,r){var w=this.label(a,g,f,r,null,null,null,null,"button"),G=0;w.attr(x({padding:8,r:2},c));var e,v,p,l;c=x({fill:"#f7f7f7",stroke:"#cccccc","stroke-width":1,style:{color:"#333333",cursor:"pointer",fontWeight:"normal"}},c);e=c.style;delete c.style;q=x(c,{fill:"#e6e6e6"},
q);v=q.style;delete q.style;D=x(c,{fill:"#e6ebf5",style:{color:"#000000",fontWeight:"bold"}},D);p=D.style;delete D.style;m=x(c,{style:{color:"#cccccc"}},m);l=m.style;delete m.style;C(w.element,y?"mouseover":"mouseenter",function(){3!==G&&w.setState(1)});C(w.element,y?"mouseout":"mouseleave",function(){3!==G&&w.setState(G)});w.setState=function(a){1!==a&&(w.state=G=a);w.removeClass(/highcharts-button-(normal|hover|pressed|disabled)/).addClass("highcharts-button-"+["normal","hover","pressed","disabled"][a||
0]);w.attr([c,q,D,m][a||0]).css([e,v,p,l][a||0])};w.attr(c).css(b({cursor:"default"},e));return w.on("click",function(a){3!==G&&d.call(w,a)})},crispLine:function(a,g){a[1]===a[4]&&(a[1]=a[4]=Math.round(a[1])-g%2/2);a[2]===a[5]&&(a[2]=a[5]=Math.round(a[2])+g%2/2);return a},path:function(a){var g={fill:"none"};v(a)?g.d=a:G(a)&&b(g,a);return this.createElement("path").attr(g)},circle:function(a,g,f){a=G(a)?a:{x:a,y:g,r:f};g=this.createElement("circle");g.xSetter=g.ySetter=function(a,g,f){f.setAttribute("c"+
g,a)};return g.attr(a)},arc:function(a,g,f,b,d,c){G(a)?(b=a,g=b.y,f=b.r,a=b.x):b={innerR:b,start:d,end:c};a=this.symbol("arc",a,g,f,f,b);a.r=f;return a},rect:function(a,g,f,b,d,c){d=G(a)?a.r:d;var w=this.createElement("rect");a=G(a)?a:void 0===a?{}:{x:a,y:g,width:Math.max(f,0),height:Math.max(b,0)};void 0!==c&&(a.strokeWidth=c,a=w.crisp(a));a.fill="none";d&&(a.r=d);w.rSetter=function(a,g,f){u(f,{rx:a,ry:a})};return w.attr(a)},setSize:function(a,g,f){var b=this.alignedObjects,d=b.length;this.width=
a;this.height=g;for(this.boxWrapper.animate({width:a,height:g},{step:function(){this.attr({viewBox:"0 0 "+this.attr("width")+" "+this.attr("height")})},duration:K(f,!0)?void 0:0});d--;)b[d].align()},g:function(a){var g=this.createElement("g");return a?g.attr({"class":"highcharts-"+a}):g},image:function(a,g,f,d,c){var w={preserveAspectRatio:"none"};1<arguments.length&&b(w,{x:g,y:f,width:d,height:c});w=this.createElement("image").attr(w);w.element.setAttributeNS?w.element.setAttributeNS("http://www.w3.org/1999/xlink",
"href",a):w.element.setAttribute("hc-svg-href",a);return w},symbol:function(a,g,f,d,c,q){var w=this,D,y=this.symbols[a],m=k(g)&&y&&this.symbols[a](Math.round(g),Math.round(f),d,c,q),x=/^url\((.*?)\)$/,G,r;y?(D=this.path(m),D.attr("fill","none"),b(D,{symbolName:a,x:g,y:f,width:d,height:c}),q&&b(D,q)):x.test(a)&&(G=a.match(x)[1],D=this.image(G),D.imgwidth=K(R[G]&&R[G].width,q&&q.width),D.imgheight=K(R[G]&&R[G].height,q&&q.height),r=function(){D.attr({width:D.width,height:D.height})},H(["width","height"],
function(a){D[a+"Setter"]=function(a,g){var f={},b=this["img"+g],d="width"===g?"translateX":"translateY";this[g]=a;k(b)&&(this.element&&this.element.setAttribute(g,b),this.alignByTranslate||(f[d]=((this[g]||0)-b)/2,this.attr(f)))}}),k(g)&&D.attr({x:g,y:f}),D.isImg=!0,k(D.imgwidth)&&k(D.imgheight)?r():(D.attr({width:0,height:0}),l("img",{onload:function(){var a=h[w.chartIndex];0===this.width&&(t(this,{position:"absolute",top:"-999em"}),p.body.appendChild(this));R[G]={width:this.width,height:this.height};
D.imgwidth=this.width;D.imgheight=this.height;D.element&&r();this.parentNode&&this.parentNode.removeChild(this);w.imgCount--;if(!w.imgCount&&a&&a.onload)a.onload()},src:G}),this.imgCount++));return D},symbols:{circle:function(a,g,f,b){return this.arc(a+f/2,g+b/2,f/2,b/2,{start:0,end:2*Math.PI,open:!1})},square:function(a,g,f,b){return["M",a,g,"L",a+f,g,a+f,g+b,a,g+b,"Z"]},triangle:function(a,g,f,b){return["M",a+f/2,g,"L",a+f,g+b,a,g+b,"Z"]},"triangle-down":function(a,g,f,b){return["M",a,g,"L",a+f,
g,a+f/2,g+b,"Z"]},diamond:function(a,g,f,b){return["M",a+f/2,g,"L",a+f,g+b/2,a+f/2,g+b,a,g+b/2,"Z"]},arc:function(a,g,f,b,d){var c=d.start,w=d.r||f,q=d.r||b||f,D=d.end-.001;f=d.innerR;b=d.open;var y=Math.cos(c),m=Math.sin(c),x=Math.cos(D),D=Math.sin(D);d=d.end-c<Math.PI?0:1;w=["M",a+w*y,g+q*m,"A",w,q,0,d,1,a+w*x,g+q*D];k(f)&&w.push(b?"M":"L",a+f*x,g+f*D,"A",f,f,0,d,0,a+f*y,g+f*m);w.push(b?"":"Z");return w},callout:function(a,g,f,b,d){var c=Math.min(d&&d.r||0,f,b),q=c+6,D=d&&d.anchorX;d=d&&d.anchorY;
var w;w=["M",a+c,g,"L",a+f-c,g,"C",a+f,g,a+f,g,a+f,g+c,"L",a+f,g+b-c,"C",a+f,g+b,a+f,g+b,a+f-c,g+b,"L",a+c,g+b,"C",a,g+b,a,g+b,a,g+b-c,"L",a,g+c,"C",a,g,a,g,a+c,g];D&&D>f?d>g+q&&d<g+b-q?w.splice(13,3,"L",a+f,d-6,a+f+6,d,a+f,d+6,a+f,g+b-c):w.splice(13,3,"L",a+f,b/2,D,d,a+f,b/2,a+f,g+b-c):D&&0>D?d>g+q&&d<g+b-q?w.splice(33,3,"L",a,d+6,a-6,d,a,d-6,a,g+c):w.splice(33,3,"L",a,b/2,D,d,a,b/2,a,g+c):d&&d>b&&D>a+q&&D<a+f-q?w.splice(23,3,"L",D+6,g+b,D,g+b+6,D-6,g+b,a+c,g+b):d&&0>d&&D>a+q&&D<a+f-q&&w.splice(3,
3,"L",D-6,g,D,g-6,D+6,g,f-c,g);return w}},clipRect:function(g,f,b,d){var c=a.uniqueKey(),q=this.createElement("clipPath").attr({id:c}).add(this.defs);g=this.rect(g,f,b,d,0).add(q);g.id=c;g.clipPath=q;g.count=0;return g},text:function(a,g,f,b){var d=!S&&this.forExport,c={};if(b&&(this.allowHTML||!this.forExport))return this.html(a,g,f);c.x=Math.round(g||0);f&&(c.y=Math.round(f));if(a||0===a)c.text=a;a=this.createElement("text").attr(c);d&&a.css({position:"absolute"});b||(a.xSetter=function(a,g,f){var b=
f.getElementsByTagName("tspan"),d,c=f.getAttribute(g),q;for(q=0;q<b.length;q++)d=b[q],d.getAttribute(g)===c&&d.setAttribute(g,a);f.setAttribute(g,a)});return a},fontMetrics:function(a,g){a=a||g&&g.style&&g.style.fontSize||this.style&&this.style.fontSize;a=/px/.test(a)?L(a):/em/.test(a)?parseFloat(a)*(g?this.fontMetrics(null,g.parentNode).f:16):12;g=24>a?a+3:Math.round(1.2*a);return{h:g,b:Math.round(.8*g),f:a}},rotCorr:function(a,g,f){var b=a;g&&f&&(b=Math.max(b*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*
e),y:b}},label:function(f,d,c,q,D,y,m,G,r){var w=this,e=w.g("button"!==r&&"label"),v=e.text=w.text("",0,0,m).attr({zIndex:1}),p,l,F=0,A=3,h=0,J,t,S,n,M,K={},L,u,O=/^url\((.*?)\)$/.test(q),R=O,P,Q,N,U;r&&e.addClass("highcharts-"+r);R=O;P=function(){return(L||0)%2/2};Q=function(){var a=v.element.style,g={};l=(void 0===J||void 0===t||M)&&k(v.textStr)&&v.getBBox();e.width=(J||l.width||0)+2*A+h;e.height=(t||l.height||0)+2*A;u=A+w.fontMetrics(a&&a.fontSize,v).b;R&&(p||(e.box=p=w.symbols[q]||O?w.symbol(q):
w.rect(),p.addClass(("button"===r?"":"highcharts-label-box")+(r?" highcharts-"+r+"-box":"")),p.add(e),a=P(),g.x=a,g.y=(G?-u:0)+a),g.width=Math.round(e.width),g.height=Math.round(e.height),p.attr(b(g,K)),K={})};N=function(){var a=h+A,g;g=G?0:u;k(J)&&l&&("center"===M||"right"===M)&&(a+={center:.5,right:1}[M]*(J-l.width));if(a!==v.x||g!==v.y)v.attr("x",a),void 0!==g&&v.attr("y",g);v.x=a;v.y=g};U=function(a,g){p?p.attr(a,g):K[a]=g};e.onAdd=function(){v.add(e);e.attr({text:f||0===f?f:"",x:d,y:c});p&&k(D)&&
e.attr({anchorX:D,anchorY:y})};e.widthSetter=function(g){J=a.isNumber(g)?g:null};e.heightSetter=function(a){t=a};e["text-alignSetter"]=function(a){M=a};e.paddingSetter=function(a){k(a)&&a!==A&&(A=e.padding=a,N())};e.paddingLeftSetter=function(a){k(a)&&a!==h&&(h=a,N())};e.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==F&&(F=a,l&&e.attr({x:S}))};e.textSetter=function(a){void 0!==a&&v.textSetter(a);Q();N()};e["stroke-widthSetter"]=function(a,g){a&&(R=!0);L=this["stroke-width"]=a;U(g,a)};
e.strokeSetter=e.fillSetter=e.rSetter=function(a,g){"fill"===g&&a&&(R=!0);U(g,a)};e.anchorXSetter=function(a,g){D=a;U(g,Math.round(a)-P()-S)};e.anchorYSetter=function(a,g){y=a;U(g,a-n)};e.xSetter=function(a){e.x=a;F&&(a-=F*((J||l.width)+2*A));S=Math.round(a);e.attr("translateX",S)};e.ySetter=function(a){n=e.y=Math.round(a);e.attr("translateY",n)};var W=e.css;return b(e,{css:function(a){if(a){var g={};a=x(a);H(e.textProps,function(f){void 0!==a[f]&&(g[f]=a[f],delete a[f])});v.css(g)}return W.call(e,
a)},getBBox:function(){return{width:l.width+2*A,height:l.height+2*A,x:l.x-A,y:l.y-A}},shadow:function(a){a&&(Q(),p&&p.shadow(a));return e},destroy:function(){g(e.element,"mouseenter");g(e.element,"mouseleave");v&&(v=v.destroy());p&&(p=p.destroy());B.prototype.destroy.call(e);e=w=Q=N=U=null}})}};a.Renderer=z})(I);(function(a){var B=a.attr,z=a.createElement,C=a.css,E=a.defined,u=a.each,h=a.extend,n=a.isFirefox,t=a.isMS,l=a.isWebKit,k=a.pInt,e=a.SVGRenderer,c=a.win,p=a.wrap;h(a.SVGElement.prototype,
{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=h(this.styles,a);C(this.element,a);return this},htmlGetBBox:function(){var a=this.element;"text"===a.nodeName&&(a.style.position="absolute");return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,
b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,p=this.y||0,v=this.textAlign||"left",f={left:0,center:.5,right:1}[v],y=this.styles;C(b,{marginLeft:c,marginTop:d});this.shadows&&u(this.shadows,function(a){C(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&u(b.childNodes,function(f){a.invertChild(f,b)});if("SPAN"===b.tagName){var G=this.rotation,F=k(this.textWidth),q=y&&y.whiteSpace,x=[G,v,b.innerHTML,this.textWidth,this.textAlign].join();x!==this.cTT&&(y=a.fontMetrics(b.style.fontSize).b,
E(G)&&this.setSpanRotation(G,f,y),C(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>F&&/[ \-]/.test(b.textContent||b.innerText)&&C(b,{width:F+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,y,f,G,v));C(b,{left:e+(this.xCorr||0)+"px",top:p+(this.yCorr||0)+"px"});l&&(y=b.offsetHeight);this.cTT=x}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,e){var d={},m=t?"-ms-transform":l?"-webkit-transform":n?"MozTransform":c.opera?"-o-transform":"";d[m]=d.transform=
"rotate("+a+"deg)";d[m+(n?"Origin":"-origin")]=d.transformOrigin=100*b+"% "+e+"px";C(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c;this.yCorr=-b}});h(e.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,m=d.renderer,v=m.isSVG,f=function(a,f){u(["opacity","visibility"],function(b){p(a,b+"Setter",function(a,b,d,c){a.call(this,b,d,c);f[d]=b})})};d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=this.textStr=a;d.htmlUpdateTransform()};
v&&f(d,d.element.style);d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,f){"align"===f&&(f="textAlign");d[f]=a;d.htmlUpdateTransform()};d.attr({text:a,x:Math.round(b),y:Math.round(c)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";d.css=d.htmlCss;v&&(d.add=function(a){var b,c=m.box.parentNode,q=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)q.push(a),a=a.parentGroup;u(q.reverse(),function(a){var y,e=B(a.element,
"class");e&&(e={className:e});b=a.div=a.div||z("div",e,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display,opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||c);y=b.style;h(a,{on:function(){d.on.apply({element:q[0].div},arguments);return a},translateXSetter:function(f,g){y.left=f+"px";a[g]=f;a.doTransform=!0},translateYSetter:function(f,g){y.top=f+"px";a[g]=f;a.doTransform=!0}});f(a,y)})}}else b=c;b.appendChild(e);d.added=!0;d.alignOnAdd&&
d.htmlUpdateTransform();return d});return d}})})(I);(function(a){var B,z,C=a.createElement,E=a.css,u=a.defined,h=a.deg2rad,n=a.discardElement,t=a.doc,l=a.each,k=a.erase,e=a.extend;B=a.extendClass;var c=a.isArray,p=a.isNumber,H=a.isObject,b=a.merge;z=a.noop;var m=a.pick,d=a.pInt,r=a.SVGElement,A=a.SVGRenderer,v=a.win;a.svg||(z={docMode8:t&&8===t.documentMode,init:function(a,b){var f=["\x3c",b,' filled\x3d"f" stroked\x3d"f"'],d=["position: ","absolute",";"],c="div"===b;("shape"===b||c)&&d.push("left:0;top:0;width:1px;height:1px;");
d.push("visibility: ",c?"hidden":"visible");f.push(' style\x3d"',d.join(""),'"/\x3e');b&&(f=c||"span"===b||"img"===b?f.join(""):a.prepVML(f),this.element=C(f));this.renderer=a},add:function(a){var f=this.renderer,b=this.element,d=f.box,c=a&&a.inverted,d=a?a.element||a:d;a&&(this.parentGroup=a);c&&f.invertChild(b,d);d.appendChild(b);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();this.className&&this.attr("class",this.className);return this},
updateTransform:r.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Math.cos(a*h),d=Math.sin(a*h);E(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11\x3d",b,", M12\x3d",-d,", M21\x3d",d,", M22\x3d",b,", sizingMethod\x3d'auto expand')"].join(""):"none"})},getSpanCorrection:function(a,b,d,c,q){var f=c?Math.cos(c*h):1,e=c?Math.sin(c*h):0,y=m(this.elemHeight,this.element.offsetHeight),r;this.xCorr=0>f&&-a;this.yCorr=0>e&&-y;r=0>f*e;this.xCorr+=e*b*(r?1-
d:d);this.yCorr-=f*b*(c?r?d:1-d:1);q&&"left"!==q&&(this.xCorr-=a*d*(0>f?-1:1),c&&(this.yCorr-=y*d*(0>e?-1:1)),E(this.element,{textAlign:q}))},pathToVML:function(a){for(var f=a.length,b=[];f--;)p(a[f])?b[f]=Math.round(10*a[f])-5:"Z"===a[f]?b[f]="x":(b[f]=a[f],!a.isArc||"wa"!==a[f]&&"at"!==a[f]||(b[f+5]===b[f+7]&&(b[f+7]+=a[f+7]>a[f+5]?1:-1),b[f+6]===b[f+8]&&(b[f+8]+=a[f+8]>a[f+6]?1:-1)));return b.join(" ")||"x"},clip:function(a){var f=this,b;a?(b=a.members,k(b,f),b.push(f),f.destroyClip=function(){k(b,
f)},a=a.getCSS(f)):(f.destroyClip&&f.destroyClip(),a={clip:f.docMode8?"inherit":"rect(auto)"});return f.css(a)},css:r.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&n(a)},destroy:function(){this.destroyClip&&this.destroyClip();return r.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=v.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var f;a=a.split(/[ ,]/);f=a.length;if(9===f||11===f)a[f-4]=a[f-2]=d(a[f-2])-10*b;return a.join(" ")},
shadow:function(a,b,c){var f=[],q,e=this.element,y=this.renderer,r,v=e.style,g,D=e.path,p,l,G,k;D&&"string"!==typeof D.value&&(D="x");l=D;if(a){G=m(a.width,3);k=(a.opacity||.15)/G;for(q=1;3>=q;q++)p=2*G+1-2*q,c&&(l=this.cutOffPath(D.value,p+.5)),g=['\x3cshape isShadow\x3d"true" strokeweight\x3d"',p,'" filled\x3d"false" path\x3d"',l,'" coordsize\x3d"10 10" style\x3d"',e.style.cssText,'" /\x3e'],r=C(y.prepVML(g),null,{left:d(v.left)+m(a.offsetX,1),top:d(v.top)+m(a.offsetY,1)}),c&&(r.cutOff=p+1),g=['\x3cstroke color\x3d"',
a.color||"#000000",'" opacity\x3d"',k*q,'"/\x3e'],C(y.prepVML(g),null,null,r),b?b.element.appendChild(r):e.parentNode.insertBefore(r,e),f.push(r);this.shadows=f}return this},updateShadows:z,setAttr:function(a,b){this.docMode8?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){(this.added?this.element:this).className=a},dashstyleSetter:function(a,b,d){(d.getElementsByTagName("stroke")[0]||C(this.renderer.prepVML(["\x3cstroke/\x3e"]),null,null,d))[b]=a||"solid";this[b]=a},dSetter:function(a,
b,d){var f=this.shadows;a=a||[];this.d=a.join&&a.join(" ");d.path=a=this.pathToVML(a);if(f)for(d=f.length;d--;)f[d].path=f[d].cutOff?this.cutOffPath(a,f[d].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,d){var f=d.nodeName;"SPAN"===f?d.style.color=a:"IMG"!==f&&(d.filled="none"!==a,this.setAttr("fillcolor",this.renderer.color(a,d,b,this)))},"fill-opacitySetter":function(a,b,d){C(this.renderer.prepVML(["\x3c",b.split("-")[0],' opacity\x3d"',a,'"/\x3e']),null,null,d)},opacitySetter:z,rotationSetter:function(a,
b,d){d=d.style;this[b]=d[b]=a;d.left=-Math.round(Math.sin(a*h)+1)+"px";d.top=Math.round(Math.cos(a*h))+"px"},strokeSetter:function(a,b,d){this.setAttr("strokecolor",this.renderer.color(a,d,b,this))},"stroke-widthSetter":function(a,b,d){d.stroked=!!a;this[b]=a;p(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,d){"inherit"===a&&(a="visible");this.shadows&&l(this.shadows,function(f){f.style[b]=a});"DIV"===d.nodeName&&(a="hidden"===
a?"-999em":0,this.docMode8||(d.style[b]=a?"visible":"hidden"),b="top");d.style[b]=a},xSetter:function(a,b,d){this[b]=a;"x"===b?b="left":"y"===b&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):d.style[b]=a},zIndexSetter:function(a,b,d){d.style[b]=a}},z["stroke-opacitySetter"]=z["fill-opacitySetter"],a.VMLElement=z=B(r,z),z.prototype.ySetter=z.prototype.widthSetter=z.prototype.heightSetter=z.prototype.xSetter,z={Element:z,isIE8:-1<v.navigator.userAgent.indexOf("MSIE 8.0"),init:function(a,
b,d){var f,c;this.alignedObjects=[];f=this.createElement("div").css({position:"relative"});c=f.element;a.appendChild(f.element);this.isVML=!0;this.box=c;this.boxWrapper=f;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(b,d,!1);if(!t.namespaces.hcv){t.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{t.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(x){t.styleSheets[0].cssText+=
"hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,d,c){var f=this.createElement(),m=H(a);return e(f,{members:[],count:0,left:(m?a.x:a)+1,top:(m?a.y:b)+1,width:(m?a.width:d)-1,height:(m?a.height:c)-1,getCSS:function(a){var b=a.element,d=b.nodeName,g=a.inverted,f=this.top-("shape"===d?b.offsetTop:0),c=this.left,b=c+this.width,q=f+this.height,f={clip:"rect("+Math.round(g?
c:f)+"px,"+Math.round(g?q:b)+"px,"+Math.round(g?b:q)+"px,"+Math.round(g?f:c)+"px)"};!g&&a.docMode8&&"DIV"===d&&e(f,{width:b+"px",height:q+"px"});return f},updateClipping:function(){l(f.members,function(a){a.element&&a.css(f.getCSS(a))})}})},color:function(b,d,c,e){var f=this,m,r=/^rgba/,v,p,g="none";b&&b.linearGradient?p="gradient":b&&b.radialGradient&&(p="pattern");if(p){var D,y,k=b.linearGradient||b.radialGradient,A,h,w,G,t,F="";b=b.stops;var n,H=[],u=function(){v=['\x3cfill colors\x3d"'+H.join(",")+
'" opacity\x3d"',w,'" o:opacity2\x3d"',h,'" type\x3d"',p,'" ',F,'focus\x3d"100%" method\x3d"any" /\x3e'];C(f.prepVML(v),null,null,d)};A=b[0];n=b[b.length-1];0<A[0]&&b.unshift([0,A[1]]);1>n[0]&&b.push([1,n[1]]);l(b,function(g,b){r.test(g[1])?(m=a.color(g[1]),D=m.get("rgb"),y=m.get("a")):(D=g[1],y=1);H.push(100*g[0]+"% "+D);b?(w=y,G=D):(h=y,t=D)});if("fill"===c)if("gradient"===p)c=k.x1||k[0]||0,b=k.y1||k[1]||0,A=k.x2||k[2]||0,k=k.y2||k[3]||0,F='angle\x3d"'+(90-180*Math.atan((k-b)/(A-c))/Math.PI)+'"',
u();else{var g=k.r,z=2*g,B=2*g,E=k.cx,V=k.cy,I=d.radialReference,T,g=function(){I&&(T=e.getBBox(),E+=(I[0]-T.x)/T.width-.5,V+=(I[1]-T.y)/T.height-.5,z*=I[2]/T.width,B*=I[2]/T.height);F='src\x3d"'+a.getOptions().global.VMLRadialGradientURL+'" size\x3d"'+z+","+B+'" origin\x3d"0.5,0.5" position\x3d"'+E+","+V+'" color2\x3d"'+t+'" ';u()};e.added?g():e.onAdd=g;g=G}else g=D}else r.test(b)&&"IMG"!==d.tagName?(m=a.color(b),e[c+"-opacitySetter"](m.get("a"),c,d),g=m.get("rgb")):(g=d.getElementsByTagName(c),
g.length&&(g[0].opacity=1,g[0].type="solid"),g=b);return g},prepVML:function(a){var b=this.isIE8;a=a.join("");b?(a=a.replace("/\x3e",' xmlns\x3d"urn:schemas-microsoft-com:vml" /\x3e'),a=-1===a.indexOf('style\x3d"')?a.replace("/\x3e",' style\x3d"display:inline-block;behavior:url(#default#VML);" /\x3e'):a.replace('style\x3d"','style\x3d"display:inline-block;behavior:url(#default#VML);')):a=a.replace("\x3c","\x3chcv:");return a},text:A.prototype.html,path:function(a){var b={coordsize:"10 10"};c(a)?b.d=
a:H(a)&&e(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,d){var f=this.symbol("circle");H(a)&&(d=a.r,b=a.y,a=a.x);f.isCircle=!0;f.r=d;return f.attr({x:a,y:b})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement("div").attr(b)},image:function(a,b,d,c,q){var f=this.createElement("img").attr({src:a});1<arguments.length&&f.attr({x:b,y:d,width:c,height:q});return f},createElement:function(a){return"rect"===a?this.symbol(a):A.prototype.createElement.call(this,
a)},invertChild:function(a,b){var f=this;b=b.style;var c="IMG"===a.tagName&&a.style;E(a,{flip:"x",left:d(b.width)-(c?d(c.top):1),top:d(b.height)-(c?d(c.left):1),rotation:-90});l(a.childNodes,function(b){f.invertChild(b,a)})},symbols:{arc:function(a,b,d,c,q){var f=q.start,e=q.end,m=q.r||d||c;d=q.innerR;c=Math.cos(f);var r=Math.sin(f),g=Math.cos(e),D=Math.sin(e);if(0===e-f)return["x"];f=["wa",a-m,b-m,a+m,b+m,a+m*c,b+m*r,a+m*g,b+m*D];q.open&&!d&&f.push("e","M",a,b);f.push("at",a-d,b-d,a+d,b+d,a+d*g,
b+d*D,a+d*c,b+d*r,"x","e");f.isArc=!0;return f},circle:function(a,b,d,c,q){q&&u(q.r)&&(d=c=2*q.r);q&&q.isCircle&&(a-=d/2,b-=c/2);return["wa",a,b,a+d,b+c,a+d,b+c/2,a+d,b+c/2,"e"]},rect:function(a,b,d,c,q){return A.prototype.symbols[u(q)&&q.r?"callout":"square"].call(0,a,b,d,c,q)}}},a.VMLRenderer=B=function(){this.init.apply(this,arguments)},B.prototype=b(A.prototype,z),a.Renderer=B);A.prototype.measureSpanWidth=function(a,b){var d=t.createElement("span");a=t.createTextNode(a);d.appendChild(a);E(d,
b);this.box.appendChild(d);b=d.offsetWidth;n(d);return b}})(I);(function(a){function B(){var l=a.defaultOptions.global,k=t.moment;if(l.timezone){if(k)return function(a){return-k.tz(a,l.timezone).utcOffset()};a.error(25)}return l.useUTC&&l.getTimezoneOffset}function z(){var l=a.defaultOptions.global,k,e=l.useUTC,c=e?"getUTC":"get",p=e?"setUTC":"set";a.Date=k=l.Date||t.Date;k.hcTimezoneOffset=e&&l.timezoneOffset;k.hcGetTimezoneOffset=B();k.hcMakeTime=function(a,b,c,d,r,p){var m;e?(m=k.UTC.apply(0,arguments),
m+=u(m)):m=(new k(a,b,n(c,1),n(d,0),n(r,0),n(p,0))).getTime();return m};E("Minutes Hours Day Date Month FullYear".split(" "),function(a){k["hcGet"+a]=c+a});E("Milliseconds Seconds Minutes Hours Date Month FullYear".split(" "),function(a){k["hcSet"+a]=p+a})}var C=a.color,E=a.each,u=a.getTZOffset,h=a.merge,n=a.pick,t=a.win;a.defaultOptions={colors:"#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1".split(" "),symbols:["circle","diamond","square","triangle","triangle-down"],
lang:{loading:"Loading...",months:"January February March April May June July August September October November December".split(" "),shortMonths:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),weekdays:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),decimalPoint:".",numericSymbols:"kMGTPE".split(""),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:" "},global:{useUTC:!0,VMLRadialGradientURL:"http://code.highcharts.com/5.0.9/gfx/vml-radial-gradient.png"},
chart:{borderRadius:0,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}},width:null,height:null,borderColor:"#335cad",backgroundColor:"#ffffff",plotBorderColor:"#cccccc"},title:{text:"Chart title",align:"center",margin:15,widthAdjust:-44},subtitle:{text:"",align:"center",widthAdjust:-44},plotOptions:{},labels:{style:{position:"absolute",color:"#333333"}},legend:{enabled:!0,align:"center",layout:"horizontal",
labelFormatter:function(){return this.name},borderColor:"#999999",borderRadius:0,navigation:{activeColor:"#003399",inactiveColor:"#cccccc"},itemStyle:{color:"#333333",fontSize:"12px",fontWeight:"bold"},itemHoverStyle:{color:"#000000"},itemHiddenStyle:{color:"#cccccc"},shadow:!1,itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},squareSymbol:!0,symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",
top:"45%"},style:{position:"absolute",backgroundColor:"#ffffff",opacity:.5,textAlign:"center"}},tooltip:{enabled:!0,animation:a.svg,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},footerFormat:"",padding:8,snap:a.isTouchDevice?25:10,backgroundColor:C("#f7f7f7").setOpacity(.85).get(),borderWidth:1,headerFormat:'\x3cspan style\x3d"font-size: 10px"\x3e{point.key}\x3c/span\x3e\x3cbr/\x3e',
pointFormat:'\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e',shadow:!0,style:{color:"#333333",cursor:"default",fontSize:"12px",pointerEvents:"none",whiteSpace:"nowrap"}},credits:{enabled:!0,href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#999999",fontSize:"9px"},text:"Highcharts.com"}};a.setOptions=function(l){a.defaultOptions=h(!0,a.defaultOptions,l);z();
return a.defaultOptions};a.getOptions=function(){return a.defaultOptions};a.defaultPlotOptions=a.defaultOptions.plotOptions;z()})(I);(function(a){var B=a.arrayMax,z=a.arrayMin,C=a.defined,E=a.destroyObjectProperties,u=a.each,h=a.erase,n=a.merge,t=a.pick;a.PlotLineOrBand=function(a,k){this.axis=a;k&&(this.options=k,this.id=k.id)};a.PlotLineOrBand.prototype={render:function(){var a=this,k=a.axis,e=k.horiz,c=a.options,p=c.label,h=a.label,b=c.to,m=c.from,d=c.value,r=C(m)&&C(b),A=C(d),v=a.svgElem,f=!v,
y=[],G,F=c.color,q=t(c.zIndex,0),x=c.events,y={"class":"highcharts-plot-"+(r?"band ":"line ")+(c.className||"")},J={},u=k.chart.renderer,L=r?"bands":"lines",g=k.log2lin;k.isLog&&(m=g(m),b=g(b),d=g(d));A?(y={stroke:F,"stroke-width":c.width},c.dashStyle&&(y.dashstyle=c.dashStyle)):r&&(F&&(y.fill=F),c.borderWidth&&(y.stroke=c.borderColor,y["stroke-width"]=c.borderWidth));J.zIndex=q;L+="-"+q;(F=k[L])||(k[L]=F=u.g("plot-"+L).attr(J).add());f&&(a.svgElem=v=u.path().attr(y).add(F));if(A)y=k.getPlotLinePath(d,
v.strokeWidth());else if(r)y=k.getPlotBandPath(m,b,c);else return;if(f&&y&&y.length){if(v.attr({d:y}),x)for(G in c=function(b){v.on(b,function(g){x[b].apply(a,[g])})},x)c(G)}else v&&(y?(v.show(),v.animate({d:y})):(v.hide(),h&&(a.label=h=h.destroy())));p&&C(p.text)&&y&&y.length&&0<k.width&&0<k.height&&!y.flat?(p=n({align:e&&r&&"center",x:e?!r&&4:10,verticalAlign:!e&&r&&"middle",y:e?r?16:10:r?6:-4,rotation:e&&!r&&90},p),this.renderLabel(p,y,r,q)):h&&h.hide();return a},renderLabel:function(a,k,e,c){var p=
this.label,l=this.axis.chart.renderer;p||(p={align:a.textAlign||a.align,rotation:a.rotation,"class":"highcharts-plot-"+(e?"band":"line")+"-label "+(a.className||"")},p.zIndex=c,this.label=p=l.text(a.text,0,0,a.useHTML).attr(p).add(),p.css(a.style));c=[k[1],k[4],e?k[6]:k[1]];k=[k[2],k[5],e?k[7]:k[2]];e=z(c);l=z(k);p.align(a,!1,{x:e,y:l,width:B(c)-e,height:B(k)-l});p.show()},destroy:function(){h(this.axis.plotLinesAndBands,this);delete this.axis;E(this)}};a.AxisPlotLineOrBandExtension={getPlotBandPath:function(a,
k){k=this.getPlotLinePath(k,null,null,!0);(a=this.getPlotLinePath(a,null,null,!0))&&k?(a.flat=a.toString()===k.toString(),a.push(k[4],k[5],k[1],k[2],"z")):a=null;return a},addPlotBand:function(a){return this.addPlotBandOrLine(a,"plotBands")},addPlotLine:function(a){return this.addPlotBandOrLine(a,"plotLines")},addPlotBandOrLine:function(l,k){var e=(new a.PlotLineOrBand(this,l)).render(),c=this.userOptions;e&&(k&&(c[k]=c[k]||[],c[k].push(l)),this.plotLinesAndBands.push(e));return e},removePlotBandOrLine:function(a){for(var k=
this.plotLinesAndBands,e=this.options,c=this.userOptions,p=k.length;p--;)k[p].id===a&&k[p].destroy();u([e.plotLines||[],c.plotLines||[],e.plotBands||[],c.plotBands||[]],function(c){for(p=c.length;p--;)c[p].id===a&&h(c,c[p])})}}})(I);(function(a){var B=a.correctFloat,z=a.defined,C=a.destroyObjectProperties,E=a.isNumber,u=a.merge,h=a.pick,n=a.deg2rad;a.Tick=function(a,l,k,e){this.axis=a;this.pos=l;this.type=k||"";this.isNew=!0;k||e||this.addLabel()};a.Tick.prototype={addLabel:function(){var a=this.axis,
l=a.options,k=a.chart,e=a.categories,c=a.names,p=this.pos,n=l.labels,b=a.tickPositions,m=p===b[0],d=p===b[b.length-1],c=e?h(e[p],c[p],p):p,e=this.label,b=b.info,r;a.isDatetimeAxis&&b&&(r=l.dateTimeLabelFormats[b.higherRanks[p]||b.unitName]);this.isFirst=m;this.isLast=d;l=a.labelFormatter.call({axis:a,chart:k,isFirst:m,isLast:d,dateTimeLabelFormat:r,value:a.isLog?B(a.lin2log(c)):c});z(e)?e&&e.attr({text:l}):(this.labelLength=(this.label=e=z(l)&&n.enabled?k.renderer.text(l,0,0,n.useHTML).css(u(n.style)).add(a.labelGroup):
null)&&e.getBBox().width,this.rotation=0)},getLabelSize:function(){return this.label?this.label.getBBox()[this.axis.horiz?"height":"width"]:0},handleOverflow:function(a){var l=this.axis,k=a.x,e=l.chart.chartWidth,c=l.chart.spacing,p=h(l.labelLeft,Math.min(l.pos,c[3])),c=h(l.labelRight,Math.max(l.pos+l.len,e-c[1])),t=this.label,b=this.rotation,m={left:0,center:.5,right:1}[l.labelAlign],d=t.getBBox().width,r=l.getSlotWidth(),A=r,v=1,f,y={};if(b)0>b&&k-m*d<p?f=Math.round(k/Math.cos(b*n)-p):0<b&&k+m*
d>c&&(f=Math.round((e-k)/Math.cos(b*n)));else if(e=k+(1-m)*d,k-m*d<p?A=a.x+A*(1-m)-p:e>c&&(A=c-a.x+A*m,v=-1),A=Math.min(r,A),A<r&&"center"===l.labelAlign&&(a.x+=v*(r-A-m*(r-Math.min(d,A)))),d>A||l.autoRotation&&(t.styles||{}).width)f=A;f&&(y.width=f,(l.options.labels.style||{}).textOverflow||(y.textOverflow="ellipsis"),t.css(y))},getPosition:function(a,l,k,e){var c=this.axis,p=c.chart,h=e&&p.oldChartHeight||p.chartHeight;return{x:a?c.translate(l+k,null,null,e)+c.transB:c.left+c.offset+(c.opposite?
(e&&p.oldChartWidth||p.chartWidth)-c.right-c.left:0),y:a?h-c.bottom+c.offset-(c.opposite?c.height:0):h-c.translate(l+k,null,null,e)-c.transB}},getLabelPosition:function(a,h,k,e,c,p,H,b){var m=this.axis,d=m.transA,r=m.reversed,l=m.staggerLines,v=m.tickRotCorr||{x:0,y:0},f=c.y;z(f)||(f=0===m.side?k.rotation?-8:-k.getBBox().height:2===m.side?v.y+8:Math.cos(k.rotation*n)*(v.y-k.getBBox(!1,0).height/2));a=a+c.x+v.x-(p&&e?p*d*(r?-1:1):0);h=h+f-(p&&!e?p*d*(r?1:-1):0);l&&(k=H/(b||1)%l,m.opposite&&(k=l-k-
1),h+=m.labelOffset/l*k);return{x:a,y:Math.round(h)}},getMarkPath:function(a,h,k,e,c,p){return p.crispLine(["M",a,h,"L",a+(c?0:-k),h+(c?k:0)],e)},renderGridLine:function(a,h,k){var e=this.axis,c=e.options,p=this.gridLine,l={},b=this.pos,m=this.type,d=e.tickmarkOffset,r=e.chart.renderer,A=m?m+"Grid":"grid",v=c[A+"LineWidth"],f=c[A+"LineColor"],c=c[A+"LineDashStyle"];p||(l.stroke=f,l["stroke-width"]=v,c&&(l.dashstyle=c),m||(l.zIndex=1),a&&(l.opacity=0),this.gridLine=p=r.path().attr(l).addClass("highcharts-"+
(m?m+"-":"")+"grid-line").add(e.gridGroup));if(!a&&p&&(a=e.getPlotLinePath(b+d,p.strokeWidth()*k,a,!0)))p[this.isNew?"attr":"animate"]({d:a,opacity:h})},renderMark:function(a,l,k){var e=this.axis,c=e.options,p=e.chart.renderer,n=this.type,b=n?n+"Tick":"tick",m=e.tickSize(b),d=this.mark,r=!d,A=a.x;a=a.y;var v=h(c[b+"Width"],!n&&e.isXAxis?1:0),c=c[b+"Color"];m&&(e.opposite&&(m[0]=-m[0]),r&&(this.mark=d=p.path().addClass("highcharts-"+(n?n+"-":"")+"tick").add(e.axisGroup),d.attr({stroke:c,"stroke-width":v})),
d[r?"attr":"animate"]({d:this.getMarkPath(A,a,m[0],d.strokeWidth()*k,e.horiz,p),opacity:l}))},renderLabel:function(a,l,k,e){var c=this.axis,p=c.horiz,n=c.options,b=this.label,m=n.labels,d=m.step,r=c.tickmarkOffset,A=!0,v=a.x;a=a.y;b&&E(v)&&(b.xy=a=this.getLabelPosition(v,a,b,p,m,r,e,d),this.isFirst&&!this.isLast&&!h(n.showFirstLabel,1)||this.isLast&&!this.isFirst&&!h(n.showLastLabel,1)?A=!1:!p||c.isRadial||m.step||m.rotation||l||0===k||this.handleOverflow(a),d&&e%d&&(A=!1),A&&E(a.y)?(a.opacity=k,
b[this.isNew?"attr":"animate"](a)):b.attr("y",-9999),this.isNew=!1)},render:function(a,l,k){var e=this.axis,c=e.horiz,p=this.getPosition(c,this.pos,e.tickmarkOffset,l),n=p.x,b=p.y,e=c&&n===e.pos+e.len||!c&&b===e.pos?-1:1;k=h(k,1);this.isActive=!0;this.renderGridLine(l,k,e);this.renderMark(p,k,e);this.renderLabel(p,l,k,a)},destroy:function(){C(this,this.axis)}}})(I);(function(a){var B=a.addEvent,z=a.animObject,C=a.arrayMax,E=a.arrayMin,u=a.AxisPlotLineOrBandExtension,h=a.color,n=a.correctFloat,t=a.defaultOptions,
l=a.defined,k=a.deg2rad,e=a.destroyObjectProperties,c=a.each,p=a.extend,H=a.fireEvent,b=a.format,m=a.getMagnitude,d=a.grep,r=a.inArray,A=a.isArray,v=a.isNumber,f=a.isString,y=a.merge,G=a.normalizeTickInterval,F=a.pick,q=a.PlotLineOrBand,x=a.removeEvent,J=a.splat,K=a.syncTimeout,L=a.Tick;a.Axis=function(){this.init.apply(this,arguments)};a.Axis.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",
year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"},x:0},minPadding:.01,maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},
defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05,minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],
x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},init:function(a,b){var g=b.isX;this.chart=a;this.horiz=a.inverted?!g:g;this.isXAxis=g;this.coll=this.coll||(g?"xAxis":"yAxis");this.opposite=b.opposite;this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3);this.setOptions(b);var d=this.options,c=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.reversed=d.reversed;this.visible=
!1!==d.visible;this.zoomEnabled=!1!==d.zoomEnabled;this.hasNames="category"===c||!0===d.categories;this.categories=d.categories||this.hasNames;this.names=this.names||[];this.isLog="logarithmic"===c;this.isDatetimeAxis="datetime"===c;this.positiveValuesOnly=this.isLog&&!this.allowNegativeLog;this.isLinked=l(d.linkedTo);this.ticks={};this.labelEdge=[];this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;
this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stacksTouched=0;this.min=this.max=null;this.crosshair=F(d.crosshair,J(a.options.tooltip.crosshairs)[g?0:1],!1);var f;b=this.options.events;-1===r(this,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this));this.series=this.series||[];a.inverted&&g&&void 0===this.reversed&&(this.reversed=!0);this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in b)B(this,f,b[f]);this.lin2log=d.linearToLogConverter||
this.lin2log;this.isLog&&(this.val2lin=this.log2lin,this.lin2val=this.lin2log)},setOptions:function(a){this.options=y(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],y(t[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,d=this.value,c=g.categories,f=this.dateTimeLabelFormat,q=t.lang,e=q.numericSymbols,q=q.numericSymbolMagnitude||1E3,w=e&&e.length,
m,r=g.options.labels.format,g=g.isLog?Math.abs(d):g.tickInterval;if(r)m=b(r,this);else if(c)m=d;else if(f)m=a.dateFormat(f,d);else if(w&&1E3<=g)for(;w--&&void 0===m;)c=Math.pow(q,w+1),g>=c&&0===10*d%c&&null!==e[w]&&0!==d&&(m=a.numberFormat(d/c,-1)+e[w]);void 0===m&&(m=1E4<=Math.abs(d)?a.numberFormat(d,-1):a.numberFormat(d,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();
c(a.series,function(g){if(g.visible||!b.options.chart.ignoreHiddenSeries){var c=g.options,f=c.threshold,q;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=f&&(f=null);if(a.isXAxis)c=g.xData,c.length&&(g=E(c),v(g)||g instanceof Date||(c=d(c,function(a){return v(a)}),g=E(c)),a.dataMin=Math.min(F(a.dataMin,c[0]),g),a.dataMax=Math.max(F(a.dataMax,c[0]),C(c)));else if(g.getExtremes(),q=g.dataMax,g=g.dataMin,l(g)&&l(q)&&(a.dataMin=Math.min(F(a.dataMin,g),g),a.dataMax=Math.max(F(a.dataMax,q),q)),l(f)&&(a.threshold=
f),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,d,c,f,q){var g=this.linkedParent||this,D=1,e=0,m=c?g.oldTransA:g.transA;c=c?g.oldMin:g.min;var r=g.minPixelPadding;f=(g.isOrdinal||g.isBroken||g.isLog&&f)&&g.lin2val;m||(m=g.transA);d&&(D*=-1,e=g.len);g.reversed&&(D*=-1,e-=D*(g.sector||g.len));b?(a=(a*D+e-r)/m+c,f&&(a=g.lin2val(a))):(f&&(a=g.val2lin(a)),a=D*(a-c)*m+e+D*r+(v(q)?m*q:0));return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,
!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,d,c,f){var g=this.chart,q=this.left,D=this.top,e,m,r=d&&g.oldChartHeight||g.chartHeight,p=d&&g.oldChartWidth||g.chartWidth,x;e=this.transB;var k=function(a,b,g){if(a<b||a>g)c?a=Math.min(Math.max(b,a),g):x=!0;return a};f=F(f,this.translate(a,null,null,d));a=d=Math.round(f+e);e=m=Math.round(r-f-e);v(f)?this.horiz?(e=D,m=r-this.bottom,a=d=k(a,q,q+this.width)):(a=q,d=
p-this.right,e=m=k(e,D,D+this.height)):x=!0;return x&&!c?null:g.renderer.crispLine(["M",a,e,"L",d,m],b||1)},getLinearTickPositions:function(a,b,d){var g,c=n(Math.floor(b/a)*a);d=n(Math.ceil(d/a)*a);var f=[];if(this.single)return[b];for(b=c;b<=d;){f.push(b);b=n(b+a);if(b===g)break;g=b}return f},getMinorTickPositions:function(){var a=this,b=a.options,d=a.tickPositions,f=a.minorTickInterval,q=[],e=a.pointRangePadding||0,m=a.min-e,e=a.max+e,r=e-m;if(r&&r/f<a.len/3)if(a.isLog)c(this.paddedTicks,function(b,
g,d){g&&q.push.apply(q,a.getLogTickPositions(f,d[g-1],d[g],!0))});else if(a.isDatetimeAxis&&"auto"===b.minorTickInterval)q=q.concat(a.getTimeTicks(a.normalizeTimeTickInterval(f),m,e,b.startOfWeek));else for(b=m+(d[0]-m)%f;b<=e&&b!==q[0];b+=f)q.push(b);0!==q.length&&a.trimTicks(q);return q},adjustForMinRange:function(){var a=this.options,b=this.min,d=this.max,f,q=this.dataMax-this.dataMin>=this.minRange,e,m,r,p,v,x;this.isXAxis&&void 0===this.minRange&&!this.isLog&&(l(a.min)||l(a.max)?this.minRange=
null:(c(this.series,function(a){p=a.xData;for(m=v=a.xIncrement?1:p.length-1;0<m;m--)if(r=p[m]-p[m-1],void 0===e||r<e)e=r}),this.minRange=Math.min(5*e,this.dataMax-this.dataMin)));d-b<this.minRange&&(x=this.minRange,f=(x-d+b)/2,f=[b-f,F(a.min,b-f)],q&&(f[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=C(f),d=[b+x,F(a.max,b+x)],q&&(d[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),d=E(d),d-b<x&&(f[0]=d-x,f[1]=F(a.min,d-x),b=C(f)));this.min=b;this.max=d},getClosest:function(){var a;this.categories?
a=1:c(this.series,function(b){var g=b.closestPointRange,d=b.visible||!b.chart.options.chart.ignoreHiddenSeries;!b.noSharedTooltip&&l(g)&&d&&(a=l(a)?Math.min(a,g):g)});return a},nameToX:function(a){var b=A(this.categories),g=b?this.categories:this.names,d=a.options.x,c;a.series.requireSorting=!1;l(d)||(d=!1===this.options.uniqueNames?a.series.autoIncrement():r(a.name,g));-1===d?b||(c=g.length):c=d;this.names[c]=a.name;return c},updateNames:function(){var a=this;0<this.names.length&&(this.names.length=
0,this.minRange=void 0,c(this.series||[],function(b){b.xIncrement=null;if(!b.points||b.isDirtyData)b.processData(),b.generatePoints();c(b.points,function(g,d){var c;g.options&&(c=a.nameToX(g),c!==g.x&&(g.x=c,b.xData[d]=c))})}))},setAxisTranslation:function(a){var b=this,g=b.max-b.min,d=b.axisPointRange||0,q,e=0,m=0,r=b.linkedParent,p=!!b.categories,v=b.transA,x=b.isXAxis;if(x||p||d)q=b.getClosest(),r?(e=r.minPointOffset,m=r.pointRangePadding):c(b.series,function(a){var g=p?1:x?F(a.options.pointRange,
q,0):b.axisPointRange||0;a=a.options.pointPlacement;d=Math.max(d,g);b.single||(e=Math.max(e,f(a)?0:g/2),m=Math.max(m,"on"===a?0:g))}),r=b.ordinalSlope&&q?b.ordinalSlope/q:1,b.minPointOffset=e*=r,b.pointRangePadding=m*=r,b.pointRange=Math.min(d,g),x&&(b.closestPointRange=q);a&&(b.oldTransA=v);b.translationSlope=b.transA=v=b.options.staticScale||b.len/(g+m||1);b.transB=b.horiz?b.left:b.bottom;b.minPixelPadding=v*e},minFromRange:function(){return this.max-this.range},setTickInterval:function(b){var g=
this,d=g.chart,f=g.options,q=g.isLog,e=g.log2lin,r=g.isDatetimeAxis,p=g.isXAxis,x=g.isLinked,k=f.maxPadding,h=f.minPadding,y=f.tickInterval,A=f.tickPixelInterval,J=g.categories,t=g.threshold,u=g.softThreshold,L,K,z,B;r||J||x||this.getTickAmount();z=F(g.userMin,f.min);B=F(g.userMax,f.max);x?(g.linkedParent=d[g.coll][f.linkedTo],d=g.linkedParent.getExtremes(),g.min=F(d.min,d.dataMin),g.max=F(d.max,d.dataMax),f.type!==g.linkedParent.options.type&&a.error(11,1)):(!u&&l(t)&&(g.dataMin>=t?(L=t,h=0):g.dataMax<=
t&&(K=t,k=0)),g.min=F(z,L,g.dataMin),g.max=F(B,K,g.dataMax));q&&(g.positiveValuesOnly&&!b&&0>=Math.min(g.min,F(g.dataMin,g.min))&&a.error(10,1),g.min=n(e(g.min),15),g.max=n(e(g.max),15));g.range&&l(g.max)&&(g.userMin=g.min=z=Math.max(g.min,g.minFromRange()),g.userMax=B=g.max,g.range=null);H(g,"foundExtremes");g.beforePadding&&g.beforePadding();g.adjustForMinRange();!(J||g.axisPointRange||g.usePercentage||x)&&l(g.min)&&l(g.max)&&(e=g.max-g.min)&&(!l(z)&&h&&(g.min-=e*h),!l(B)&&k&&(g.max+=e*k));v(f.floor)?
g.min=Math.max(g.min,f.floor):v(f.softMin)&&(g.min=Math.min(g.min,f.softMin));v(f.ceiling)?g.max=Math.min(g.max,f.ceiling):v(f.softMax)&&(g.max=Math.max(g.max,f.softMax));u&&l(g.dataMin)&&(t=t||0,!l(z)&&g.min<t&&g.dataMin>=t?g.min=t:!l(B)&&g.max>t&&g.dataMax<=t&&(g.max=t));g.tickInterval=g.min===g.max||void 0===g.min||void 0===g.max?1:x&&!y&&A===g.linkedParent.options.tickPixelInterval?y=g.linkedParent.tickInterval:F(y,this.tickAmount?(g.max-g.min)/Math.max(this.tickAmount-1,1):void 0,J?1:(g.max-
g.min)*A/Math.max(g.len,A));p&&!b&&c(g.series,function(a){a.processData(g.min!==g.oldMin||g.max!==g.oldMax)});g.setAxisTranslation(!0);g.beforeSetTickPositions&&g.beforeSetTickPositions();g.postProcessTickInterval&&(g.tickInterval=g.postProcessTickInterval(g.tickInterval));g.pointRange&&!y&&(g.tickInterval=Math.max(g.pointRange,g.tickInterval));b=F(f.minTickInterval,g.isDatetimeAxis&&g.closestPointRange);!y&&g.tickInterval<b&&(g.tickInterval=b);r||q||y||(g.tickInterval=G(g.tickInterval,null,m(g.tickInterval),
F(f.allowDecimals,!(.5<g.tickInterval&&5>g.tickInterval&&1E3<g.max&&9999>g.max)),!!this.tickAmount));this.tickAmount||(g.tickInterval=g.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,d=a.tickPositions,c=a.tickPositioner,f=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===a.minorTickInterval&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.single=
this.min===this.max&&l(this.min)&&!this.tickAmount&&!1!==a.allowDecimals;this.tickPositions=b=d&&d.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b=[b[0],b.pop()]),this.tickPositions=b,c&&(c=c.apply(this,
[this.min,this.max])))&&(this.tickPositions=b=c);this.paddedTicks=b.slice(0);this.trimTicks(b,f,q);this.isLinked||(this.single&&(this.min-=.5,this.max+=.5),d||c||this.adjustTickAmount())},trimTicks:function(a,b,d){var g=a[0],c=a[a.length-1],f=this.minPointOffset||0;if(!this.isLinked){if(b)this.min=g;else for(;this.min-f>a[0];)a.shift();if(d)this.max=c;else for(;this.max+f<a[a.length-1];)a.pop();0===a.length&&l(g)&&a.push((c+g)/2)}},alignToOthers:function(){var a={},b,d=this.options;!1===this.chart.options.chart.alignTicks||
!1===d.alignTicks||this.isLog||c(this.chart[this.coll],function(g){var d=g.options,d=[g.horiz?d.left:d.top,d.width,d.height,d.pane].join();g.series.length&&(a[d]?b=!0:a[d]=1)});return b},getTickAmount:function(){var a=this.options,b=a.tickAmount,d=a.tickPixelInterval;!l(a.tickInterval)&&this.len<d&&!this.isRadial&&!this.isLog&&a.startOnTick&&a.endOnTick&&(b=2);!b&&this.alignToOthers()&&(b=Math.ceil(this.len/d)+1);4>b&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=
this.tickInterval,b=this.tickPositions,d=this.tickAmount,c=this.finalTickAmt,f=b&&b.length;if(f<d){for(;b.length<d;)b.push(n(b[b.length-1]+a));this.transA*=(f-1)/(d-1);this.max=b[b.length-1]}else f>d&&(this.tickInterval*=2,this.setTickPositions());if(l(c)){for(a=d=b.length;a--;)(3===c&&1===a%2||2>=c&&0<a&&a<d-1)&&b.splice(a,1);this.finalTickAmt=void 0}},setScale:function(){var a,b;this.oldMin=this.min;this.oldMax=this.max;this.oldAxisLength=this.len;this.setAxisSize();b=this.len!==this.oldAxisLength;
c(this.series,function(b){if(b.isDirtyData||b.isDirty||b.xAxis.isDirty)a=!0});b||a||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax||this.alignToOthers()?(this.resetStacks&&this.resetStacks(),this.forceRedraw=!1,this.getSeriesExtremes(),this.setTickInterval(),this.oldUserMin=this.userMin,this.oldUserMax=this.userMax,this.isDirty||(this.isDirty=b||this.min!==this.oldMin||this.max!==this.oldMax)):this.cleanStacks&&this.cleanStacks()},setExtremes:function(a,
b,d,f,q){var g=this,e=g.chart;d=F(d,!0);c(g.series,function(a){delete a.kdTree});q=p(q,{min:a,max:b});H(g,"setExtremes",q,function(){g.userMin=a;g.userMax=b;g.eventArgs=q;d&&e.redraw(f)})},zoom:function(a,b){var g=this.dataMin,d=this.dataMax,c=this.options,f=Math.min(g,F(c.min,g)),c=Math.max(d,F(c.max,d));if(a!==this.min||b!==this.max)this.allowZoomOutside||(l(g)&&(a<f&&(a=f),a>c&&(a=c)),l(d)&&(b<f&&(b=f),b>c&&(b=c))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});
return!0},setAxisSize:function(){var a=this.chart,b=this.options,d=b.offsets||[0,0,0,0],c=this.horiz,f=F(b.width,a.plotWidth-d[3]+d[1]),q=F(b.height,a.plotHeight-d[0]+d[2]),e=F(b.top,a.plotTop+d[0]),b=F(b.left,a.plotLeft+d[3]),d=/%$/;d.test(q)&&(q=Math.round(parseFloat(q)/100*a.plotHeight));d.test(e)&&(e=Math.round(parseFloat(e)/100*a.plotHeight+a.plotTop));this.left=b;this.top=e;this.width=f;this.height=q;this.bottom=a.chartHeight-q-e;this.right=a.chartWidth-f-b;this.len=Math.max(c?f:q,0);this.pos=
c?b:e},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?n(b(this.min)):this.min,max:a?n(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,d=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=d:d>a?a=d:b<a&&(a=b);return this.translate(a,0,1,0,1)},autoLabelAlign:function(a){a=(F(a,0)-90*this.side+720)%360;return 15<a&&165>a?"right":195<a&&345>a?"left":"center"},
tickSize:function(a){var b=this.options,g=b[a+"Length"],d=F(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(d&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,d]},labelMetrics:function(){return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[0]&&this.ticks[0].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,d=this.tickInterval,f=d,q=this.len/(((this.categories?1:0)+this.max-this.min)/d),e,m=a.rotation,r=this.labelMetrics(),p,x=
Number.MAX_VALUE,v,h=function(a){a/=q||1;a=1<a?Math.ceil(a):1;return a*d};b?(v=!a.staggerLines&&!a.step&&(l(m)?[m]:q<F(a.autoRotationLimit,80)&&a.autoRotation))&&c(v,function(a){var b;if(a===m||a&&-90<=a&&90>=a)p=h(Math.abs(r.h/Math.sin(k*a))),b=p+Math.abs(a/360),b<x&&(x=b,e=a,f=p)}):a.step||(f=h(r.h));this.autoRotation=v;this.labelRotation=F(e,m);return f},getSlotWidth:function(){var a=this.chart,b=this.horiz,d=this.options.labels,c=Math.max(this.tickPositions.length-(this.categories?0:1),1),f=a.margin[3];
return b&&2>(d.step||0)&&!d.rotation&&(this.staggerLines||1)*this.len/c||!b&&(f&&f-a.spacing[3]||.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,d=this.tickPositions,q=this.ticks,e=this.options.labels,m=this.horiz,r=this.getSlotWidth(),p=Math.max(1,Math.round(r-2*(e.padding||5))),x={},v=this.labelMetrics(),k=e.style&&e.style.textOverflow,h,l=0,A,n;f(e.rotation)||(x.rotation=e.rotation||0);c(d,function(a){(a=q[a])&&a.labelLength>l&&(l=a.labelLength)});this.maxLabelLength=
l;if(this.autoRotation)l>p&&l>v.h?x.rotation=this.labelRotation:this.labelRotation=0;else if(r&&(h={width:p+"px"},!k))for(h.textOverflow="clip",A=d.length;!m&&A--;)if(n=d[A],p=q[n].label)p.styles&&"ellipsis"===p.styles.textOverflow?p.css({textOverflow:"clip"}):q[n].labelLength>r&&p.css({width:r+"px"}),p.getBBox().height>this.len/d.length-(v.h-v.f)&&(p.specCss={textOverflow:"ellipsis"});x.rotation&&(h={width:(l>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},k||(h.textOverflow="ellipsis"));
if(this.labelAlign=e.align||this.autoLabelAlign(this.labelRotation))x.align=this.labelAlign;c(d,function(a){var b=(a=q[a])&&a.label;b&&(b.attr(x),h&&b.css(y(h,b.specCss)),delete b.specCss,a.rotation=x.rotation)});this.tickRotCorr=b.rotCorr(v.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||l(this.min)&&l(this.max)&&!!this.tickPositions},addTitle:function(a){var b=this.chart.renderer,d=this.horiz,g=this.opposite,c=this.options.title,f;this.axisTitle||((f=c.textAlign)||
(f=(d?{low:"left",middle:"center",high:"right"}:{low:g?"right":"left",middle:"center",high:g?"left":"right"})[c.align]),this.axisTitle=b.text(c.text,0,0,c.useHTML).attr({zIndex:7,rotation:c.rotation||0,align:f}).addClass("highcharts-axis-title").css(c.style).add(this.axisGroup),this.axisTitle.isNew=!0);this.axisTitle[a?"show":"hide"](!0)},generateTick:function(a){var b=this.ticks;b[a]?b[a].addLabel():b[a]=new L(this,a)},getOffset:function(){var a=this,b=a.chart,d=b.renderer,f=a.options,q=a.tickPositions,
e=a.ticks,m=a.horiz,r=a.side,p=b.inverted?[1,0,3,2][r]:r,x,v,h=0,k,y=0,A=f.title,n=f.labels,G=0,J=b.axisOffset,b=b.clipOffset,t=[-1,1,1,-1][r],u,H=f.className,L=a.axisParent,K=this.tickSize("tick");x=a.hasData();a.showAxis=v=x||F(f.showEmpty,!0);a.staggerLines=a.horiz&&n.staggerLines;a.axisGroup||(a.gridGroup=d.g("grid").attr({zIndex:f.gridZIndex||1}).addClass("highcharts-"+this.coll.toLowerCase()+"-grid "+(H||"")).add(L),a.axisGroup=d.g("axis").attr({zIndex:f.zIndex||2}).addClass("highcharts-"+this.coll.toLowerCase()+
" "+(H||"")).add(L),a.labelGroup=d.g("axis-labels").attr({zIndex:n.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels "+(H||"")).add(L));if(x||a.isLinked)c(q,function(b,d){a.generateTick(b,d)}),a.renderUnsquish(),!1===n.reserveSpace||0!==r&&2!==r&&{1:"left",3:"right"}[r]!==a.labelAlign&&"center"!==a.labelAlign||c(q,function(a){G=Math.max(e[a].getLabelSize(),G)}),a.staggerLines&&(G*=a.staggerLines,a.labelOffset=G*(a.opposite?-1:1));else for(u in e)e[u].destroy(),delete e[u];A&&A.text&&
!1!==A.enabled&&(a.addTitle(v),v&&(h=a.axisTitle.getBBox()[m?"height":"width"],k=A.offset,y=l(k)?0:F(A.margin,m?5:10)));a.renderLine();a.offset=t*F(f.offset,J[r]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};d=0===r?-a.labelMetrics().h:2===r?a.tickRotCorr.y:0;y=Math.abs(G)+y;G&&(y=y-d+t*(m?F(n.y,a.tickRotCorr.y+8*t):n.x));a.axisTitleMargin=F(k,y);J[r]=Math.max(J[r],a.axisTitleMargin+h+t*a.offset,y,x&&q.length&&K?K[0]+t*a.offset:0);f=f.offset?0:2*Math.floor(a.axisLine.strokeWidth()/2);b[p]=Math.max(b[p],
f)},getLinePath:function(a){var b=this.chart,d=this.opposite,g=this.offset,f=this.horiz,c=this.left+(d?this.width:0)+g,g=b.chartHeight-this.bottom-(d?this.height:0)+g;d&&(a*=-1);return b.renderer.crispLine(["M",f?this.left:c,f?g:this.top,"L",f?b.chartWidth-this.right:c,f?g:b.chartHeight-this.bottom],a)},renderLine:function(){this.axisLine||(this.axisLine=this.chart.renderer.path().addClass("highcharts-axis-line").add(this.axisGroup),this.axisLine.attr({stroke:this.options.lineColor,"stroke-width":this.options.lineWidth,
zIndex:7}))},getTitlePosition:function(){var a=this.horiz,b=this.left,d=this.top,f=this.len,c=this.options.title,q=a?b:d,e=this.opposite,m=this.offset,r=c.x||0,p=c.y||0,x=this.chart.renderer.fontMetrics(c.style&&c.style.fontSize,this.axisTitle).f,f={low:q+(a?0:f),middle:q+f/2,high:q+(a?f:0)}[c.align],b=(a?d+this.height:b)+(a?1:-1)*(e?-1:1)*this.axisTitleMargin+(2===this.side?x:0);return{x:a?f+r:b+(e?this.width:0)+m+r,y:a?b+p-(e?this.height:0)+m:f+p}},renderMinorTick:function(a){var b=this.chart.hasRendered&&
v(this.oldMin),d=this.minorTicks;d[a]||(d[a]=new L(this,a,"minor"));b&&d[a].isNew&&d[a].render(null,!0);d[a].render(null,!1,1)},renderTick:function(a,b){var d=this.isLinked,g=this.ticks,f=this.chart.hasRendered&&v(this.oldMin);if(!d||a>=this.min&&a<=this.max)g[a]||(g[a]=new L(this,a)),f&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var a=this,b=a.chart,d=a.options,f=a.isLog,e=a.lin2log,m=a.isLinked,r=a.tickPositions,p=a.axisTitle,x=a.ticks,v=a.minorTicks,h=a.alternateBands,k=
d.stackLabels,y=d.alternateGridColor,l=a.tickmarkOffset,A=a.axisLine,n=a.showAxis,G=z(b.renderer.globalAnimation),J,t;a.labelEdge.length=0;a.overlap=!1;c([x,v,h],function(a){for(var b in a)a[b].isActive=!1});if(a.hasData()||m)a.minorTickInterval&&!a.categories&&c(a.getMinorTickPositions(),function(b){a.renderMinorTick(b)}),r.length&&(c(r,function(b,d){a.renderTick(b,d)}),l&&(0===a.min||a.single)&&(x[-1]||(x[-1]=new L(a,-1,null,!0)),x[-1].render(-1))),y&&c(r,function(d,g){t=void 0!==r[g+1]?r[g+1]+
l:a.max-l;0===g%2&&d<a.max&&t<=a.max+(b.polar?-l:l)&&(h[d]||(h[d]=new q(a)),J=d+l,h[d].options={from:f?e(J):J,to:f?e(t):t,color:y},h[d].render(),h[d].isActive=!0)}),a._addedPlotLB||(c((d.plotLines||[]).concat(d.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0);c([x,v,h],function(a){var d,g,f=[],c=G.duration;for(d in a)a[d].isActive||(a[d].render(d,!1,0),a[d].isActive=!1,f.push(d));K(function(){for(g=f.length;g--;)a[f[g]]&&!a[f[g]].isActive&&(a[f[g]].destroy(),delete a[f[g]])},
a!==h&&b.hasRendered&&c?c:0)});A&&(A[A.isPlaced?"animate":"attr"]({d:this.getLinePath(A.strokeWidth())}),A.isPlaced=!0,A[n?"show":"hide"](!0));p&&n&&(p[p.isNew?"attr":"animate"](a.getTitlePosition()),p.isNew=!1);k&&k.enabled&&a.renderStackTotals();a.isDirty=!1},redraw:function(){this.visible&&(this.render(),c(this.plotLinesAndBands,function(a){a.render()}));c(this.series,function(a){a.isDirty=!0})},keepProps:"extKey hcEvents names series userMax userMin".split(" "),destroy:function(a){var b=this,
d=b.stacks,g,f=b.plotLinesAndBands,q;a||x(b);for(g in d)e(d[g]),d[g]=null;c([b.ticks,b.minorTicks,b.alternateBands],function(a){e(a)});if(f)for(a=f.length;a--;)f[a].destroy();c("stackTotalGroup axisLine axisTitle axisGroup gridGroup labelGroup cross".split(" "),function(a){b[a]&&(b[a]=b[a].destroy())});for(q in b)b.hasOwnProperty(q)&&-1===r(q,b.keepProps)&&delete b[q]},drawCrosshair:function(a,b){var d,f=this.crosshair,g=F(f.snap,!0),c,q=this.cross;a||(a=this.cross&&this.cross.e);this.crosshair&&
!1!==(l(b)||!g)?(g?l(b)&&(c=this.isXAxis?b.plotX:this.len-b.plotY):c=a&&(this.horiz?a.chartX-this.pos:this.len-a.chartY+this.pos),l(c)&&(d=this.getPlotLinePath(b&&(this.isXAxis?b.x:F(b.stackY,b.y)),null,null,null,c)||null),l(d)?(b=this.categories&&!this.isRadial,q||(this.cross=q=this.chart.renderer.path().addClass("highcharts-crosshair highcharts-crosshair-"+(b?"category ":"thin ")+f.className).attr({zIndex:F(f.zIndex,2)}).add(),q.attr({stroke:f.color||(b?h("#ccd6eb").setOpacity(.25).get():"#cccccc"),
"stroke-width":F(f.width,1)}),f.dashStyle&&q.attr({dashstyle:f.dashStyle})),q.show().attr({d:d}),b&&!f.width&&q.attr({"stroke-width":this.transA}),this.cross.e=a):this.hideCrosshair()):this.hideCrosshair()},hideCrosshair:function(){this.cross&&this.cross.hide()}};p(a.Axis.prototype,u)})(I);(function(a){var B=a.Axis,z=a.Date,C=a.dateFormat,E=a.defaultOptions,u=a.defined,h=a.each,n=a.extend,t=a.getMagnitude,l=a.getTZOffset,k=a.normalizeTickInterval,e=a.pick,c=a.timeUnits;B.prototype.getTimeTicks=function(a,
k,b,m){var d=[],r={},p=E.global.useUTC,v,f=new z(k-Math.abs(l(k))),y=z.hcMakeTime,G=a.unitRange,t=a.count,q;if(u(k)){f[z.hcSetMilliseconds](G>=c.second?0:t*Math.floor(f.getMilliseconds()/t));if(G>=c.second)f[z.hcSetSeconds](G>=c.minute?0:t*Math.floor(f.getSeconds()/t));if(G>=c.minute)f[z.hcSetMinutes](G>=c.hour?0:t*Math.floor(f[z.hcGetMinutes]()/t));if(G>=c.hour)f[z.hcSetHours](G>=c.day?0:t*Math.floor(f[z.hcGetHours]()/t));if(G>=c.day)f[z.hcSetDate](G>=c.month?1:t*Math.floor(f[z.hcGetDate]()/t));
G>=c.month&&(f[z.hcSetMonth](G>=c.year?0:t*Math.floor(f[z.hcGetMonth]()/t)),v=f[z.hcGetFullYear]());if(G>=c.year)f[z.hcSetFullYear](v-v%t);if(G===c.week)f[z.hcSetDate](f[z.hcGetDate]()-f[z.hcGetDay]()+e(m,1));v=f[z.hcGetFullYear]();m=f[z.hcGetMonth]();var x=f[z.hcGetDate](),J=f[z.hcGetHours]();if(z.hcTimezoneOffset||z.hcGetTimezoneOffset)q=(!p||!!z.hcGetTimezoneOffset)&&(b-k>4*c.month||l(k)!==l(b)),f=f.getTime(),f=new z(f+l(f));p=f.getTime();for(k=1;p<b;)d.push(p),p=G===c.year?y(v+k*t,0):G===c.month?
y(v,m+k*t):!q||G!==c.day&&G!==c.week?q&&G===c.hour?y(v,m,x,J+k*t):p+G*t:y(v,m,x+k*t*(G===c.day?1:7)),k++;d.push(p);G<=c.hour&&1E4>d.length&&h(d,function(a){0===a%18E5&&"000000000"===C("%H%M%S%L",a)&&(r[a]="day")})}d.info=n(a,{higherRanks:r,totalRange:G*t});return d};B.prototype.normalizeTimeTickInterval=function(a,e){var b=e||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,
3,4,6]],["year",null]];e=b[b.length-1];var m=c[e[0]],d=e[1],r;for(r=0;r<b.length&&!(e=b[r],m=c[e[0]],d=e[1],b[r+1]&&a<=(m*d[d.length-1]+c[b[r+1][0]])/2);r++);m===c.year&&a<5*m&&(d=[1,2,5]);a=k(a/m,d,"year"===e[0]?Math.max(t(a/m),1):1);return{unitRange:m,count:a,unitName:e[0]}}})(I);(function(a){var B=a.Axis,z=a.getMagnitude,C=a.map,E=a.normalizeTickInterval,u=a.pick;B.prototype.getLogTickPositions=function(a,n,t,l){var k=this.options,e=this.len,c=this.lin2log,p=this.log2lin,h=[];l||(this._minorAutoInterval=
null);if(.5<=a)a=Math.round(a),h=this.getLinearTickPositions(a,n,t);else if(.08<=a)for(var e=Math.floor(n),b,m,d,r,A,k=.3<a?[1,2,4]:.15<a?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];e<t+1&&!A;e++)for(m=k.length,b=0;b<m&&!A;b++)d=p(c(e)*k[b]),d>n&&(!l||r<=t)&&void 0!==r&&h.push(r),r>t&&(A=!0),r=d;else n=c(n),t=c(t),a=k[l?"minorTickInterval":"tickInterval"],a=u("auto"===a?null:a,this._minorAutoInterval,k.tickPixelInterval/(l?5:1)*(t-n)/((l?e/this.tickPositions.length:e)||1)),a=E(a,null,z(a)),h=C(this.getLinearTickPositions(a,
n,t),p),l||(this._minorAutoInterval=a/5);l||(this.tickInterval=a);return h};B.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};B.prototype.lin2log=function(a){return Math.pow(10,a)}})(I);(function(a){var B=a.dateFormat,z=a.each,C=a.extend,E=a.format,u=a.isNumber,h=a.map,n=a.merge,t=a.pick,l=a.splat,k=a.syncTimeout,e=a.timeUnits;a.Tooltip=function(){this.init.apply(this,arguments)};a.Tooltip.prototype={init:function(a,e){this.chart=a;this.options=e;this.crosshairs=[];this.now={x:0,y:0};
this.isHidden=!0;this.split=e.split&&!a.inverted;this.shared=e.shared||this.split},cleanSplit:function(a){z(this.chart.series,function(c){var e=c&&c.tt;e&&(!e.isActive||a?c.tt=e.destroy():e.isActive=!1)})},getLabel:function(){var a=this.chart.renderer,e=this.options;this.label||(this.split?this.label=a.g("tooltip"):(this.label=a.label("",0,0,e.shape||"callout",null,null,e.useHTML,null,"tooltip").attr({padding:e.padding,r:e.borderRadius}),this.label.attr({fill:e.backgroundColor,"stroke-width":e.borderWidth}).css(e.style).shadow(e.shadow)),
this.label.attr({zIndex:8}).add());return this.label},update:function(a){this.destroy();this.init(this.chart,n(!0,this.options,a))},destroy:function(){this.label&&(this.label=this.label.destroy());this.split&&this.tt&&(this.cleanSplit(this.chart,!0),this.tt=this.tt.destroy());clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,e,k,b){var c=this,d=c.now,r=!1!==c.options.animation&&!c.isHidden&&(1<Math.abs(a-d.x)||1<Math.abs(e-d.y)),p=c.followPointer||1<c.len;C(d,{x:r?(2*
d.x+a)/3:a,y:r?(d.y+e)/2:e,anchorX:p?void 0:r?(2*d.anchorX+k)/3:k,anchorY:p?void 0:r?(d.anchorY+b)/2:b});c.getLabel().attr(d);r&&(clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){c&&c.move(a,e,k,b)},32))},hide:function(a){var c=this;clearTimeout(this.hideTimer);a=t(a,this.options.hideDelay,500);this.isHidden||(this.hideTimer=k(function(){c.getLabel()[a?"fadeOut":"hide"]();c.isHidden=!0},a))},getAnchor:function(a,e){var c,b=this.chart,m=b.inverted,d=b.plotTop,r=b.plotLeft,
p=0,v=0,f,k;a=l(a);c=a[0].tooltipPos;this.followPointer&&e&&(void 0===e.chartX&&(e=b.pointer.normalize(e)),c=[e.chartX-b.plotLeft,e.chartY-d]);c||(z(a,function(a){f=a.series.yAxis;k=a.series.xAxis;p+=a.plotX+(!m&&k?k.left-r:0);v+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!m&&f?f.top-d:0)}),p/=a.length,v/=a.length,c=[m?b.plotWidth-v:p,this.shared&&!m&&1<a.length&&e?e.chartY-d:m?b.plotHeight-p:v]);return h(c,Math.round)},getPosition:function(a,e,k){var b=this.chart,c=this.distance,d={},r=k.h||0,
p,v=["y",b.chartHeight,e,k.plotY+b.plotTop,b.plotTop,b.plotTop+b.plotHeight],f=["x",b.chartWidth,a,k.plotX+b.plotLeft,b.plotLeft,b.plotLeft+b.plotWidth],h=!this.followPointer&&t(k.ttBelow,!b.inverted===!!k.negative),l=function(a,b,f,g,q,e){var m=f<g-c,x=g+c+f<b,v=g-c-f;g+=c;if(h&&x)d[a]=g;else if(!h&&m)d[a]=v;else if(m)d[a]=Math.min(e-f,0>v-r?v:v-r);else if(x)d[a]=Math.max(q,g+r+f>b?g:g+r);else return!1},n=function(a,b,f,g){var q;g<c||g>b-c?q=!1:d[a]=g<f/2?1:g>b-f/2?b-f-2:g-f/2;return q},q=function(a){var b=
v;v=f;f=b;p=a},x=function(){!1!==l.apply(0,v)?!1!==n.apply(0,f)||p||(q(!0),x()):p?d.x=d.y=0:(q(!0),x())};(b.inverted||1<this.len)&&q();x();return d},defaultFormatter:function(a){var c=this.points||l(this),e;e=[a.tooltipFooterHeaderFormatter(c[0])];e=e.concat(a.bodyFormatter(c));e.push(a.tooltipFooterHeaderFormatter(c[0],!0));return e},refresh:function(a,e){var c,b=this.options,m,d=a,r,p={},v=[];c=b.formatter||this.defaultFormatter;var p=this.shared,f;clearTimeout(this.hideTimer);this.followPointer=
l(d)[0].series.tooltipOptions.followPointer;r=this.getAnchor(d,e);e=r[0];m=r[1];!p||d.series&&d.series.noSharedTooltip?p=d.getLabelConfig():(z(d,function(a){a.setState("hover");v.push(a.getLabelConfig())}),p={x:d[0].category,y:d[0].y},p.points=v,d=d[0]);this.len=v.length;p=c.call(p,this);f=d.series;this.distance=t(f.tooltipOptions.distance,16);!1===p?this.hide():(c=this.getLabel(),this.isHidden&&c.attr({opacity:1}).show(),this.split?this.renderSplit(p,a):(c.attr({text:p&&p.join?p.join(""):p}),c.removeClass(/highcharts-color-[\d]+/g).addClass("highcharts-color-"+
t(d.colorIndex,f.colorIndex)),c.attr({stroke:b.borderColor||d.color||f.color||"#666666"}),this.updatePosition({plotX:e,plotY:m,negative:d.negative,ttBelow:d.ttBelow,h:r[2]||0})),this.isHidden=!1)},renderSplit:function(c,e){var p=this,b=[],m=this.chart,d=m.renderer,r=!0,k=this.options,v,f=this.getLabel();z(c.slice(0,e.length+1),function(a,c){c=e[c-1]||{isHeader:!0,plotX:e[0].plotX};var h=c.series||p,q=h.tt,x=c.series||{},l="highcharts-color-"+t(c.colorIndex,x.colorIndex,"none");q||(h.tt=q=d.label(null,
null,null,"callout").addClass("highcharts-tooltip-box "+l).attr({padding:k.padding,r:k.borderRadius,fill:k.backgroundColor,stroke:c.color||x.color||"#333333","stroke-width":k.borderWidth}).add(f));q.isActive=!0;q.attr({text:a});q.css(k.style);a=q.getBBox();x=a.width+q.strokeWidth();c.isHeader?(v=a.height,x=Math.max(0,Math.min(c.plotX+m.plotLeft-x/2,m.chartWidth-x))):x=c.plotX+m.plotLeft-t(k.distance,16)-x;0>x&&(r=!1);a=(c.series&&c.series.yAxis&&c.series.yAxis.pos)+(c.plotY||0);a-=m.plotTop;b.push({target:c.isHeader?
m.plotHeight+v:a,rank:c.isHeader?1:0,size:h.tt.getBBox().height+1,point:c,x:x,tt:q})});this.cleanSplit();a.distribute(b,m.plotHeight+v);z(b,function(a){var b=a.point,d=b.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:r||b.isHeader?a.x:b.plotX+m.plotLeft+t(k.distance,16),y:a.pos+m.plotTop,anchorX:b.isHeader?b.plotX+m.plotLeft:b.plotX+d.xAxis.pos,anchorY:b.isHeader?a.pos+m.plotTop-15:b.plotY+d.yAxis.pos})})},updatePosition:function(a){var c=this.chart,e=this.getLabel(),e=(this.options.positioner||
this.getPosition).call(this,e.width,e.height,a);this.move(Math.round(e.x),Math.round(e.y||0),a.plotX+c.plotLeft,a.plotY+c.plotTop)},getDateFormat:function(a,p,k,b){var c=B("%m-%d %H:%M:%S.%L",p),d,r,h={millisecond:15,second:12,minute:9,hour:6,day:3},v="millisecond";for(r in e){if(a===e.week&&+B("%w",p)===k&&"00:00:00.000"===c.substr(6)){r="week";break}if(e[r]>a){r=v;break}if(h[r]&&c.substr(h[r])!=="01-01 00:00:00.000".substr(h[r]))break;"week"!==r&&(v=r)}r&&(d=b[r]);return d},getXDateFormat:function(a,
e,k){e=e.dateTimeLabelFormats;var b=k&&k.closestPointRange;return(b?this.getDateFormat(b,a.x,k.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){var c=e?"footer":"header";e=a.series;var b=e.tooltipOptions,m=b.xDateFormat,d=e.xAxis,r=d&&"datetime"===d.options.type&&u(a.key),c=b[c+"Format"];r&&!m&&(m=this.getXDateFormat(a,b,d));r&&m&&(c=c.replace("{point.key}","{point.key:"+m+"}"));return E(c,{point:a,series:e})},bodyFormatter:function(a){return h(a,function(a){var c=
a.series.tooltipOptions;return(c.pointFormatter||a.point.tooltipFormatter).call(a.point,c.pointFormat)})}}})(I);(function(a){var B=a.addEvent,z=a.attr,C=a.charts,E=a.color,u=a.css,h=a.defined,n=a.doc,t=a.each,l=a.extend,k=a.fireEvent,e=a.offset,c=a.pick,p=a.removeEvent,H=a.splat,b=a.Tooltip,m=a.win;a.Pointer=function(a,b){this.init(a,b)};a.Pointer.prototype={init:function(a,e){this.options=e;this.chart=a;this.runChartClick=e.chart.events&&!!e.chart.events.click;this.pinchDown=[];this.lastValidTouch=
{};b&&e.tooltip.enabled&&(a.tooltip=new b(a,e.tooltip),this.followTouchMove=c(e.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,d=b.options.chart,e=d.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(e=c(d.pinchType,e));this.zoomX=a=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=a&&!b||e&&b;this.zoomVert=e&&!b||a&&b;this.hasZoom=a||e},normalize:function(a,b){var d,c;a=a||m.event;a.target||(a.target=a.srcElement);c=a.touches?a.touches.length?a.touches.item(0):
a.changedTouches[0]:a;b||(this.chartPosition=b=e(this.chart.container));void 0===c.pageX?(d=Math.max(a.x,a.clientX-b.left),b=a.y):(d=c.pageX-b.left,b=c.pageY-b.top);return l(a,{chartX:Math.round(d),chartY:Math.round(b)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};t(this.chart.axes,function(d){b[d.isXAxis?"xAxis":"yAxis"].push({axis:d,value:d.toValue(a[d.horiz?"chartX":"chartY"])})});return b},getKDPoints:function(a,b,e){var d=[],f,m,r;t(a,function(a){f=a.noSharedTooltip&&b;m=!b&&a.directTouch;
a.visible&&!f&&!m&&c(a.options.enableMouseTracking,!0)&&(r=a.searchPoint(e,!f&&1===a.kdDimensions))&&r.series&&d.push(r)});d.sort(function(a,d){var f=a.distX-d.distX,c=a.dist-d.dist,e=(d.series.group&&d.series.group.zIndex)-(a.series.group&&a.series.group.zIndex);return 0!==f&&b?f:0!==c?c:0!==e?e:a.series.index>d.series.index?-1:1});if(b)for(a=d.length;a--;)(d[a].x!==d[0].x||d[a].series.noSharedTooltip)&&d.splice(a,1);return d},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=
a.parentNode;return b},getHoverData:function(a,b,e,m,f,k){var d=a;a=b;var r;if(m)f?(r=[],t(e,function(a){var b=a.noSharedTooltip&&f,e=!f&&a.directTouch;a.visible&&!b&&!e&&c(a.options.enableMouseTracking,!0)&&(a=a.searchKDTree({clientX:d.clientX,plotY:d.plotY},!b&&1===a.kdDimensions))&&a.series&&r.push(a)}),0===r.length&&(r=[d])):r=[d];else{if(a&&!a.options.stickyTracking)r=this.getKDPoints([a],f,k);else{if(!f)if(a)a.options.stickyTracking||(e=[a]);else for(m=0;m<e.length;m++)if(e[m].directTouch||
!e[m].options.stickyTracking)e=[];r=this.getKDPoints(e,f,k)}a=(d=r[0])&&d.series}r.sort(function(a,b){return a.series.index-b.series.index});return{hoverPoint:d,hoverSeries:a,hoverPoints:r}},runPointActions:function(b,c){var d=this.chart,e=d.tooltip,f=e?e.shared:!1,m=c||d.hoverPoint,r=m&&m.series||d.hoverSeries;c=this.getHoverData(m,r,d.series,!!c||r&&r.directTouch,f,b);var k,q,m=c.hoverPoint;k=(r=c.hoverSeries)&&r.tooltipOptions.followPointer;q=(f=f&&m&&!m.series.noSharedTooltip)?c.hoverPoints:[m];
if(m&&(m!==d.hoverPoint||e&&e.isHidden)){t(d.hoverPoints||[],function(b){-1===a.inArray(b,q)&&b.setState()});t(q||[],function(a){a.setState("hover")});if(d.hoverSeries!==r)r.onMouseOver();r&&!r.directTouch&&(d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut"),m.firePointEvent("mouseOver"));d.hoverPoints=q;d.hoverPoint=m;e&&e.refresh(f?q:m,b)}else k&&e&&!e.isHidden&&(m=e.getAnchor([{}],b),e.updatePosition({plotX:m[0],plotY:m[1]}));this.unDocMouseMove||(this.unDocMouseMove=B(n,"mousemove",function(b){var d=
C[a.hoverChartIndex];if(d)d.pointer.onDocumentMouseMove(b)}));t(q,function(a){t(d.axes,function(d){(!a||a.series&&a.series[d.coll]===d)&&d.drawCrosshair(b,a)})})},reset:function(a,b){var d=this.chart,c=d.hoverSeries,f=d.hoverPoint,e=d.hoverPoints,m=d.tooltip,r=m&&m.shared?e:f;a&&r&&t(H(r),function(b){b.series.isCartesian&&void 0===b.plotX&&(a=!1)});if(a)m&&r&&(m.refresh(r),f&&(f.setState(f.state,!0),t(d.axes,function(a){a.crosshair&&a.drawCrosshair(null,f)})));else{if(f)f.onMouseOut();e&&t(e,function(a){a.setState()});
if(c)c.onMouseOut();m&&m.hide(b);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());t(d.axes,function(a){a.hideCrosshair()});this.hoverX=d.hoverPoints=d.hoverPoint=null}},scaleGroups:function(a,b){var d=this.chart,c;t(d.series,function(f){c=a||f.getPlotBox();f.xAxis&&f.xAxis.zoomEnabled&&f.group&&(f.group.attr(c),f.markerGroup&&(f.markerGroup.attr(c),f.markerGroup.clip(b?d.clipRect:null)),f.dataLabelsGroup&&f.dataLabelsGroup.attr(c))});d.clipRect.attr(b||d.clipBox)},dragStart:function(a){var b=
this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,d=b.options.chart,c=a.chartX,f=a.chartY,e=this.zoomHor,m=this.zoomVert,k=b.plotLeft,q=b.plotTop,x=b.plotWidth,p=b.plotHeight,h,l=this.selectionMarker,g=this.mouseDownX,n=this.mouseDownY,t=d.panKey&&a[d.panKey+"Key"];l&&l.touch||(c<k?c=k:c>k+x&&(c=k+x),f<q?f=q:f>q+p&&(f=q+p),this.hasDragged=Math.sqrt(Math.pow(g-c,2)+Math.pow(n-f,2)),10<this.hasDragged&&
(h=b.isInsidePlot(g-k,n-q),b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&h&&!t&&!l&&(this.selectionMarker=l=b.renderer.rect(k,q,e?1:x,m?1:p,0).attr({fill:d.selectionMarkerFill||E("#335cad").setOpacity(.25).get(),"class":"highcharts-selection-marker",zIndex:7}).add()),l&&e&&(c-=g,l.attr({width:Math.abs(c),x:(0<c?0:c)+g})),l&&m&&(c=f-n,l.attr({height:Math.abs(c),y:(0<c?0:c)+n})),h&&!l&&d.panning&&b.pan(a,d.panning)))},drop:function(a){var b=this,d=this.chart,c=this.hasPinched;if(this.selectionMarker){var f=
{originalEvent:a,xAxis:[],yAxis:[]},e=this.selectionMarker,m=e.attr?e.attr("x"):e.x,p=e.attr?e.attr("y"):e.y,q=e.attr?e.attr("width"):e.width,x=e.attr?e.attr("height"):e.height,n;if(this.hasDragged||c)t(d.axes,function(d){if(d.zoomEnabled&&h(d.min)&&(c||b[{xAxis:"zoomX",yAxis:"zoomY"}[d.coll]])){var e=d.horiz,g="touchend"===a.type?d.minPixelPadding:0,r=d.toValue((e?m:p)+g),e=d.toValue((e?m+q:p+x)-g);f[d.coll].push({axis:d,min:Math.min(r,e),max:Math.max(r,e)});n=!0}}),n&&k(d,"selection",f,function(a){d.zoom(l(a,
c?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();c&&this.scaleGroups()}d&&(u(d.container,{cursor:d._cursor}),d.cancelClick=10<this.hasDragged,d.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[])},onContainerMouseDown:function(a){a=this.normalize(a);this.zoomOption(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(b){C[a.hoverChartIndex]&&C[a.hoverChartIndex].pointer.drop(b)},onDocumentMouseMove:function(a){var b=this.chart,
d=this.chartPosition;a=this.normalize(a,d);!d||this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)||this.reset()},onContainerMouseLeave:function(b){var d=C[a.hoverChartIndex];d&&(b.relatedTarget||b.toElement)&&(d.pointer.reset(),d.pointer.chartPosition=null)},onContainerMouseMove:function(b){var d=this.chart;h(a.hoverChartIndex)&&C[a.hoverChartIndex]&&C[a.hoverChartIndex].mouseIsDown||(a.hoverChartIndex=d.index);b=this.normalize(b);b.returnValue=!1;
"mousedown"===d.mouseIsDown&&this.drag(b);!this.inClass(b.target,"highcharts-tracker")&&!d.isInsidePlot(b.chartX-d.plotLeft,b.chartY-d.plotTop)||d.openMenu||this.runPointActions(b)},inClass:function(a,b){for(var d;a;){if(d=z(a,"class")){if(-1!==d.indexOf(b))return!0;if(-1!==d.indexOf("highcharts-container"))return!1}a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries;a=a.relatedTarget||a.toElement;if(!(!b||!a||b.options.stickyTracking||this.inClass(a,"highcharts-tooltip")||
this.inClass(a,"highcharts-series-"+b.index)&&this.inClass(a,"highcharts-tracker")))b.onMouseOut()},onContainerClick:function(a){var b=this.chart,d=b.hoverPoint,c=b.plotLeft,f=b.plotTop;a=this.normalize(a);b.cancelClick||(d&&this.inClass(a.target,"highcharts-tracker")?(k(d.series,"click",l(a,{point:d})),b.hoverPoint&&d.firePointEvent("click",a)):(l(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-c,a.chartY-f)&&k(b,"click",a)))},setDOMEvents:function(){var b=this,c=b.chart.container;c.onmousedown=
function(a){b.onContainerMouseDown(a)};c.onmousemove=function(a){b.onContainerMouseMove(a)};c.onclick=function(a){b.onContainerClick(a)};B(c,"mouseleave",b.onContainerMouseLeave);1===a.chartCount&&B(n,"mouseup",b.onDocumentMouseUp);a.hasTouch&&(c.ontouchstart=function(a){b.onContainerTouchStart(a)},c.ontouchmove=function(a){b.onContainerTouchMove(a)},1===a.chartCount&&B(n,"touchend",b.onDocumentTouchEnd))},destroy:function(){var b;p(this.chart.container,"mouseleave",this.onContainerMouseLeave);a.chartCount||
(p(n,"mouseup",this.onDocumentMouseUp),p(n,"touchend",this.onDocumentTouchEnd));clearInterval(this.tooltipTimeout);for(b in this)this[b]=null}}})(I);(function(a){var B=a.charts,z=a.each,C=a.extend,E=a.map,u=a.noop,h=a.pick;C(a.Pointer.prototype,{pinchTranslate:function(a,h,l,k,e,c){this.zoomHor&&this.pinchTranslateDirection(!0,a,h,l,k,e,c);this.zoomVert&&this.pinchTranslateDirection(!1,a,h,l,k,e,c)},pinchTranslateDirection:function(a,h,l,k,e,c,p,u){var b=this.chart,m=a?"x":"y",d=a?"X":"Y",r="chart"+
d,n=a?"width":"height",v=b["plot"+(a?"Left":"Top")],f,y,t=u||1,F=b.inverted,q=b.bounds[a?"h":"v"],x=1===h.length,J=h[0][r],K=l[0][r],L=!x&&h[1][r],g=!x&&l[1][r],D;l=function(){!x&&20<Math.abs(J-L)&&(t=u||Math.abs(K-g)/Math.abs(J-L));y=(v-K)/t+J;f=b["plot"+(a?"Width":"Height")]/t};l();h=y;h<q.min?(h=q.min,D=!0):h+f>q.max&&(h=q.max-f,D=!0);D?(K-=.8*(K-p[m][0]),x||(g-=.8*(g-p[m][1])),l()):p[m]=[K,g];F||(c[m]=y-v,c[n]=f);c=F?1/t:t;e[n]=f;e[m]=h;k[F?a?"scaleY":"scaleX":"scale"+d]=t;k["translate"+d]=c*
v+(K-c*J)},pinch:function(a){var n=this,l=n.chart,k=n.pinchDown,e=a.touches,c=e.length,p=n.lastValidTouch,H=n.hasZoom,b=n.selectionMarker,m={},d=1===c&&(n.inClass(a.target,"highcharts-tracker")&&l.runTrackerClick||n.runChartClick),r={};1<c&&(n.initiated=!0);H&&n.initiated&&!d&&a.preventDefault();E(e,function(a){return n.normalize(a)});"touchstart"===a.type?(z(e,function(a,b){k[b]={chartX:a.chartX,chartY:a.chartY}}),p.x=[k[0].chartX,k[1]&&k[1].chartX],p.y=[k[0].chartY,k[1]&&k[1].chartY],z(l.axes,function(a){if(a.zoomEnabled){var b=
l.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,c=a.toPixels(h(a.options.min,a.dataMin)),e=a.toPixels(h(a.options.max,a.dataMax)),m=Math.max(c,e);b.min=Math.min(a.pos,Math.min(c,e)-d);b.max=Math.max(a.pos+a.len,m+d)}}),n.res=!0):n.followTouchMove&&1===c?this.runPointActions(n.normalize(a)):k.length&&(b||(n.selectionMarker=b=C({destroy:u,touch:!0},l.plotBox)),n.pinchTranslate(k,e,m,b,r,p),n.hasPinched=H,n.scaleGroups(m,r),n.res&&(n.res=!1,this.reset(!1,0)))},touch:function(n,t){var l=this.chart,k,e;
if(l.index!==a.hoverChartIndex)this.onContainerMouseLeave({relatedTarget:!0});a.hoverChartIndex=l.index;1===n.touches.length?(n=this.normalize(n),(e=l.isInsidePlot(n.chartX-l.plotLeft,n.chartY-l.plotTop))&&!l.openMenu?(t&&this.runPointActions(n),"touchmove"===n.type&&(t=this.pinchDown,k=t[0]?4<=Math.sqrt(Math.pow(t[0].chartX-n.chartX,2)+Math.pow(t[0].chartY-n.chartY,2)):!1),h(k,!0)&&this.pinch(n)):t&&this.reset()):2===n.touches.length&&this.pinch(n)},onContainerTouchStart:function(a){this.zoomOption(a);
this.touch(a,!0)},onContainerTouchMove:function(a){this.touch(a)},onDocumentTouchEnd:function(h){B[a.hoverChartIndex]&&B[a.hoverChartIndex].pointer.drop(h)}})})(I);(function(a){var B=a.addEvent,z=a.charts,C=a.css,E=a.doc,u=a.extend,h=a.noop,n=a.Pointer,t=a.removeEvent,l=a.win,k=a.wrap;if(l.PointerEvent||l.MSPointerEvent){var e={},c=!!l.PointerEvent,p=function(){var a,c=[];c.item=function(a){return this[a]};for(a in e)e.hasOwnProperty(a)&&c.push({pageX:e[a].pageX,pageY:e[a].pageY,target:e[a].target});
return c},H=function(b,c,d,e){"touch"!==b.pointerType&&b.pointerType!==b.MSPOINTER_TYPE_TOUCH||!z[a.hoverChartIndex]||(e(b),e=z[a.hoverChartIndex].pointer,e[c]({type:d,target:b.currentTarget,preventDefault:h,touches:p()}))};u(n.prototype,{onContainerPointerDown:function(a){H(a,"onContainerTouchStart","touchstart",function(a){e[a.pointerId]={pageX:a.pageX,pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){H(a,"onContainerTouchMove","touchmove",function(a){e[a.pointerId]={pageX:a.pageX,
pageY:a.pageY};e[a.pointerId].target||(e[a.pointerId].target=a.currentTarget)})},onDocumentPointerUp:function(a){H(a,"onDocumentTouchEnd","touchend",function(a){delete e[a.pointerId]})},batchMSEvents:function(a){a(this.chart.container,c?"pointerdown":"MSPointerDown",this.onContainerPointerDown);a(this.chart.container,c?"pointermove":"MSPointerMove",this.onContainerPointerMove);a(E,c?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}});k(n.prototype,"init",function(a,c,d){a.call(this,c,d);this.hasZoom&&
C(c.container,{"-ms-touch-action":"none","touch-action":"none"})});k(n.prototype,"setDOMEvents",function(a){a.apply(this);(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(B)});k(n.prototype,"destroy",function(a){this.batchMSEvents(t);a.call(this)})}})(I);(function(a){var B,z=a.addEvent,C=a.css,E=a.discardElement,u=a.defined,h=a.each,n=a.isFirefox,t=a.marginNames,l=a.merge,k=a.pick,e=a.setAnimation,c=a.stableSort,p=a.win,H=a.wrap;B=a.Legend=function(a,c){this.init(a,c)};B.prototype={init:function(a,
c){this.chart=a;this.setOptions(c);c.enabled&&(this.render(),z(this.chart,"endResize",function(){this.legend.positionCheckboxes()}))},setOptions:function(a){var b=k(a.padding,8);this.options=a;this.itemStyle=a.itemStyle;this.itemHiddenStyle=l(this.itemStyle,a.itemHiddenStyle);this.itemMarginTop=a.itemMarginTop||0;this.initialItemX=this.padding=b;this.initialItemY=b-5;this.itemHeight=this.maxItemWidth=0;this.symbolWidth=k(a.symbolWidth,16);this.pages=[]},update:function(a,c){var b=this.chart;this.setOptions(l(!0,
this.options,a));this.destroy();b.isDirtyLegend=b.isDirtyBox=!0;k(c,!0)&&b.redraw()},colorizeItem:function(a,c){a.legendGroup[c?"removeClass":"addClass"]("highcharts-legend-item-hidden");var b=this.options,e=a.legendItem,m=a.legendLine,k=a.legendSymbol,f=this.itemHiddenStyle.color,b=c?b.itemStyle.color:f,p=c?a.color||f:f,h=a.options&&a.options.marker,l={fill:p},q;e&&e.css({fill:b,color:b});m&&m.attr({stroke:p});if(k){if(h&&k.isMarker&&(l=a.pointAttribs(),!c))for(q in l)l[q]=f;k.attr(l)}},positionItem:function(a){var b=
this.options,d=b.symbolPadding,b=!b.rtl,c=a._legendItemPos,e=c[0],c=c[1],k=a.checkbox;(a=a.legendGroup)&&a.element&&a.translate(b?e:this.legendWidth-e-2*d-4,c);k&&(k.x=e,k.y=c)},destroyItem:function(a){var b=a.checkbox;h(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&E(a.checkbox)},destroy:function(){function a(a){this[a]&&(this[a]=this[a].destroy())}h(this.getAllItems(),function(b){h(["legendItem","legendGroup"],a,b)});h("clipRect up down pager nav box title group".split(" "),
a,this);this.display=null},positionCheckboxes:function(a){var b=this.group&&this.group.alignAttr,d,c=this.clipHeight||this.legendHeight,e=this.titleHeight;b&&(d=b.translateY,h(this.allItems,function(m){var f=m.checkbox,k;f&&(k=d+e+f.y+(a||0)+3,C(f,{left:b.translateX+m.checkboxOffset+f.x-20+"px",top:k+"px",display:k>d-6&&k<d+c-6?"":"none"}))}))},renderTitle:function(){var a=this.padding,c=this.options.title,d=0;c.text&&(this.title||(this.title=this.chart.renderer.label(c.text,a-3,a-4,null,null,null,
null,null,"legend-title").attr({zIndex:1}).css(c.style).add(this.group)),a=this.title.getBBox(),d=a.height,this.offsetWidth=a.width,this.contentGroup.attr({translateY:d}));this.titleHeight=d},setText:function(b){var c=this.options;b.legendItem.attr({text:c.labelFormat?a.format(c.labelFormat,b):c.labelFormatter.call(b)})},renderItem:function(a){var b=this.chart,d=b.renderer,c=this.options,e="horizontal"===c.layout,p=this.symbolWidth,f=c.symbolPadding,h=this.itemStyle,n=this.itemHiddenStyle,t=this.padding,
q=e?k(c.itemDistance,20):0,x=!c.rtl,J=c.width,u=c.itemMarginBottom||0,L=this.itemMarginTop,g=this.initialItemX,D=a.legendItem,H=!a.series,z=!H&&a.series.drawLegendSymbol?a.series:a,B=z.options,B=this.createCheckboxForItem&&B&&B.showCheckbox,C=c.useHTML;D||(a.legendGroup=d.g("legend-item").addClass("highcharts-"+z.type+"-series highcharts-color-"+a.colorIndex+(a.options.className?" "+a.options.className:"")+(H?" highcharts-series-"+a.index:"")).attr({zIndex:1}).add(this.scrollGroup),a.legendItem=D=
d.text("",x?p+f:-f,this.baseline||0,C).css(l(a.visible?h:n)).attr({align:x?"left":"right",zIndex:2}).add(a.legendGroup),this.baseline||(h=h.fontSize,this.fontMetrics=d.fontMetrics(h,D),this.baseline=this.fontMetrics.f+3+L,D.attr("y",this.baseline)),this.symbolHeight=c.symbolHeight||this.fontMetrics.f,z.drawLegendSymbol(this,a),this.setItemEvents&&this.setItemEvents(a,D,C),B&&this.createCheckboxForItem(a));this.colorizeItem(a,a.visible);this.setText(a);d=D.getBBox();p=a.checkboxOffset=c.itemWidth||
a.legendItemWidth||p+f+d.width+q+(B?20:0);this.itemHeight=f=Math.round(a.legendItemHeight||d.height);e&&this.itemX-g+p>(J||b.chartWidth-2*t-g-c.x)&&(this.itemX=g,this.itemY+=L+this.lastLineHeight+u,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,p);this.lastItemY=L+this.itemY+u;this.lastLineHeight=Math.max(f,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=p:(this.itemY+=L+f+u,this.lastLineHeight=f);this.offsetWidth=J||Math.max((e?this.itemX-g-q:p)+t,
this.offsetWidth)},getAllItems:function(){var a=[];h(this.chart.series,function(b){var d=b&&b.options;b&&k(d.showInLegend,u(d.linkedTo)?!1:void 0,!0)&&(a=a.concat(b.legendItems||("point"===d.legendType?b.data:b)))});return a},adjustMargins:function(a,c){var b=this.chart,e=this.options,m=e.align.charAt(0)+e.verticalAlign.charAt(0)+e.layout.charAt(0);e.floating||h([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(d,f){d.test(m)&&!u(a[f])&&(b[t[f]]=Math.max(b[t[f]],b.legend[(f+1)%
2?"legendHeight":"legendWidth"]+[1,-1,-1,1][f]*e[f%2?"x":"y"]+k(e.margin,12)+c[f]))})},render:function(){var a=this,e=a.chart,d=e.renderer,k=a.group,p,n,f,y,t=a.box,u=a.options,q=a.padding;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=d.g("legend").attr({zIndex:7}).add(),a.contentGroup=d.g().attr({zIndex:1}).add(k),a.scrollGroup=d.g().add(a.contentGroup));a.renderTitle();p=a.getAllItems();c(p,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&
b.options.legendIndex||0)});u.reversed&&p.reverse();a.allItems=p;a.display=n=!!p.length;a.lastLineHeight=0;h(p,function(b){a.renderItem(b)});f=(u.width||a.offsetWidth)+q;y=a.lastItemY+a.lastLineHeight+a.titleHeight;y=a.handleOverflow(y);y+=q;t||(a.box=t=d.rect().addClass("highcharts-legend-box").attr({r:u.borderRadius}).add(k),t.isNew=!0);t.attr({stroke:u.borderColor,"stroke-width":u.borderWidth||0,fill:u.backgroundColor||"none"}).shadow(u.shadow);0<f&&0<y&&(t[t.isNew?"attr":"animate"](t.crisp({x:0,
y:0,width:f,height:y},t.strokeWidth())),t.isNew=!1);t[n?"show":"hide"]();a.legendWidth=f;a.legendHeight=y;h(p,function(b){a.positionItem(b)});n&&k.align(l(u,{width:f,height:y}),!0,"spacingBox");e.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,d=this.chart,c=d.renderer,e=this.options,p=e.y,d=d.spacingBox.height+("top"===e.verticalAlign?-p:p)-this.padding,p=e.maxHeight,f,l=this.clipRect,n=e.navigation,t=k(n.animation,!0),q=n.arrowSize||12,x=this.nav,u=this.pages,K=this.padding,
L,g=this.allItems,D=function(a){a?l.attr({height:a}):l&&(b.clipRect=l.destroy(),b.contentGroup.clip());b.contentGroup.div&&(b.contentGroup.div.style.clip=a?"rect("+K+"px,9999px,"+(K+a)+"px,0)":"auto")};"horizontal"!==e.layout||"middle"===e.verticalAlign||e.floating||(d/=2);p&&(d=Math.min(d,p));u.length=0;a>d&&!1!==n.enabled?(this.clipHeight=f=Math.max(d-20-this.titleHeight-K,0),this.currentPage=k(this.currentPage,1),this.fullHeight=a,h(g,function(a,b){var d=a._legendItemPos[1];a=Math.round(a.legendItem.getBBox().height);
var c=u.length;if(!c||d-u[c-1]>f&&(L||d)!==u[c-1])u.push(L||d),c++;b===g.length-1&&d+a-u[c-1]>f&&u.push(d);d!==L&&(L=d)}),l||(l=b.clipRect=c.clipRect(0,K,9999,0),b.contentGroup.clip(l)),D(f),x||(this.nav=x=c.g().attr({zIndex:1}).add(this.group),this.up=c.symbol("triangle",0,0,q,q).on("click",function(){b.scroll(-1,t)}).add(x),this.pager=c.text("",15,10).addClass("highcharts-legend-navigation").css(n.style).add(x),this.down=c.symbol("triangle-down",0,0,q,q).on("click",function(){b.scroll(1,t)}).add(x)),
b.scroll(0),a=d):x&&(D(),this.nav=x.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,m=b.length;a=this.currentPage+a;var k=this.clipHeight,p=this.options.navigation,f=this.pager,h=this.padding;a>m&&(a=m);0<a&&(void 0!==c&&e(c,this.chart),this.nav.attr({translateX:h,translateY:k+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({"class":1===a?"highcharts-legend-nav-inactive":"highcharts-legend-nav-active"}),f.attr({text:a+
"/"+m}),this.down.attr({x:18+this.pager.getBBox().width,"class":a===m?"highcharts-legend-nav-inactive":"highcharts-legend-nav-active"}),this.up.attr({fill:1===a?p.inactiveColor:p.activeColor}).css({cursor:1===a?"default":"pointer"}),this.down.attr({fill:a===m?p.inactiveColor:p.activeColor}).css({cursor:a===m?"default":"pointer"}),c=-b[a-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=a,this.positionCheckboxes(c))}};a.LegendSymbolMixin={drawRectangle:function(a,c){var b=
a.symbolHeight,e=a.options.squareSymbol;c.legendSymbol=this.chart.renderer.rect(e?(a.symbolWidth-b)/2:0,a.baseline-b+1,e?b:a.symbolWidth,b,k(a.options.symbolRadius,b/2)).addClass("highcharts-point").attr({zIndex:3}).add(c.legendGroup)},drawLineMarker:function(a){var b=this.options,c=b.marker,e=a.symbolWidth,p=a.symbolHeight,h=p/2,f=this.chart.renderer,n=this.legendGroup;a=a.baseline-Math.round(.3*a.fontMetrics.b);var t;t={"stroke-width":b.lineWidth||0};b.dashStyle&&(t.dashstyle=b.dashStyle);this.legendLine=
f.path(["M",0,a,"L",e,a]).addClass("highcharts-graph").attr(t).add(n);c&&!1!==c.enabled&&(b=Math.min(k(c.radius,h),h),0===this.symbol.indexOf("url")&&(c=l(c,{width:p,height:p}),b=0),this.legendSymbol=c=f.symbol(this.symbol,e/2-b,a-b,2*b,2*b,c).addClass("highcharts-point").add(n),c.isMarker=!0)}};(/Trident\/7\.0/.test(p.navigator.userAgent)||n)&&H(B.prototype,"positionItem",function(a,c){var b=this,e=function(){c._legendItemPos&&a.call(b,c)};e();setTimeout(e)})})(I);(function(a){var B=a.addEvent,z=
a.animate,C=a.animObject,E=a.attr,u=a.doc,h=a.Axis,n=a.createElement,t=a.defaultOptions,l=a.discardElement,k=a.charts,e=a.css,c=a.defined,p=a.each,H=a.extend,b=a.find,m=a.fireEvent,d=a.getStyle,r=a.grep,A=a.isNumber,v=a.isObject,f=a.isString,y=a.Legend,G=a.marginNames,F=a.merge,q=a.Pointer,x=a.pick,J=a.pInt,K=a.removeEvent,L=a.seriesTypes,g=a.splat,D=a.svg,S=a.syncTimeout,M=a.win,R=a.Renderer,N=a.Chart=function(){this.getArgs.apply(this,arguments)};a.chart=function(a,b,c){return new N(a,b,c)};N.prototype=
{callbacks:[],getArgs:function(){var a=[].slice.call(arguments);if(f(a[0])||a[0].nodeName)this.renderTo=a.shift();this.init(a[0],a[1])},init:function(b,c){var d,f=b.series;b.series=null;d=F(t,b);d.series=b.series=f;this.userOptions=b;b=d.chart;f=b.events;this.margin=[];this.spacing=[];this.bounds={h:{},v:{}};this.callback=c;this.isResizing=0;this.options=d;this.axes=[];this.series=[];this.hasCartesianSeries=b.showAxes;var g;this.index=k.length;k.push(this);a.chartCount++;if(f)for(g in f)B(this,g,
f[g]);this.xAxis=[];this.yAxis=[];this.pointCount=this.colorCounter=this.symbolCounter=0;this.firstRender()},initSeries:function(b){var c=this.options.chart;(c=L[b.type||c.type||c.defaultSeriesType])||a.error(17,!0);c=new c;c.init(this,b);return c},orderSeries:function(a){var b=this.series;for(a=a||0;a<b.length;a++)b[a]&&(b[a].index=a,b[a].name=b[a].name||"Series "+(b[a].index+1))},isInsidePlot:function(a,b,c){var d=c?b:a;a=c?a:b;return 0<=d&&d<=this.plotWidth&&0<=a&&a<=this.plotHeight},redraw:function(b){var c=
this.axes,d=this.series,f=this.pointer,g=this.legend,e=this.isDirtyLegend,q,k,h=this.hasCartesianSeries,x=this.isDirtyBox,l,w=this.renderer,r=w.isHidden(),n=[];this.setResponsive&&this.setResponsive(!1);a.setAnimation(b,this);r&&this.cloneRenderTo();this.layOutTitles();for(b=d.length;b--;)if(l=d[b],l.options.stacking&&(q=!0,l.isDirty)){k=!0;break}if(k)for(b=d.length;b--;)l=d[b],l.options.stacking&&(l.isDirty=!0);p(d,function(a){a.isDirty&&"point"===a.options.legendType&&(a.updateTotals&&a.updateTotals(),
e=!0);a.isDirtyData&&m(a,"updatedData")});e&&g.options.enabled&&(g.render(),this.isDirtyLegend=!1);q&&this.getStacks();h&&p(c,function(a){a.updateNames();a.setScale()});this.getMargins();h&&(p(c,function(a){a.isDirty&&(x=!0)}),p(c,function(a){var b=a.min+","+a.max;a.extKey!==b&&(a.extKey=b,n.push(function(){m(a,"afterSetExtremes",H(a.eventArgs,a.getExtremes()));delete a.eventArgs}));(x||q)&&a.redraw()}));x&&this.drawChartBox();m(this,"predraw");p(d,function(a){(x||a.isDirty)&&a.visible&&a.redraw();
a.isDirtyData=!1});f&&f.reset(!0);w.draw();m(this,"redraw");m(this,"render");r&&this.cloneRenderTo(!0);p(n,function(a){a.call()})},get:function(a){function c(b){return b.id===a||b.options&&b.options.id===a}var d,f=this.series,g;d=b(this.axes,c)||b(this.series,c);for(g=0;!d&&g<f.length;g++)d=b(f[g].points||[],c);return d},getAxes:function(){var a=this,b=this.options,c=b.xAxis=g(b.xAxis||{}),b=b.yAxis=g(b.yAxis||{});p(c,function(a,b){a.index=b;a.isX=!0});p(b,function(a,b){a.index=b});c=c.concat(b);
p(c,function(b){new h(a,b)})},getSelectedPoints:function(){var a=[];p(this.series,function(b){a=a.concat(r(b.points||[],function(a){return a.selected}))});return a},getSelectedSeries:function(){return r(this.series,function(a){return a.selected})},setTitle:function(a,b,c){var d=this,f=d.options,g;g=f.title=F({style:{color:"#333333",fontSize:f.isStock?"16px":"18px"}},f.title,a);f=f.subtitle=F({style:{color:"#666666"}},f.subtitle,b);p([["title",a,g],["subtitle",b,f]],function(a,b){var c=a[0],f=d[c],
g=a[1];a=a[2];f&&g&&(d[c]=f=f.destroy());a&&a.text&&!f&&(d[c]=d.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+c,zIndex:a.zIndex||4}).add(),d[c].update=function(a){d.setTitle(!b&&a,b&&a)},d[c].css(a.style))});d.layOutTitles(c)},layOutTitles:function(a){var b=0,c,d=this.renderer,f=this.spacingBox;p(["title","subtitle"],function(a){var c=this[a],g=this.options[a],e;c&&(e=g.style.fontSize,e=d.fontMetrics(e,c).b,c.css({width:(g.width||f.width+g.widthAdjust)+"px"}).align(H({y:b+
e+("title"===a?-3:2)},g),!1,"spacingBox"),g.floating||g.verticalAlign||(b=Math.ceil(b+c.getBBox().height)))},this);c=this.titleOffset!==b;this.titleOffset=b;!this.isDirtyBox&&c&&(this.isDirtyBox=c,this.hasRendered&&x(a,!0)&&this.isDirtyBox&&this.redraw())},getChartSize:function(){var b=this.options.chart,f=b.width,b=b.height,g=this.renderToClone||this.renderTo;c(f)||(this.containerWidth=d(g,"width"));c(b)||(this.containerHeight=d(g,"height"));this.chartWidth=Math.max(0,f||this.containerWidth||600);
this.chartHeight=Math.max(0,a.relativeLength(b,this.chartWidth)||this.containerHeight||400)},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;if(a){if(b){for(;b.childNodes.length;)this.renderTo.appendChild(b.firstChild);l(b);delete this.renderToClone}}else c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),e(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block",
"important"),u.body.appendChild(b),c&&b.appendChild(c)},setClassName:function(a){this.container.className="highcharts-container "+(a||"")},getContainer:function(){var b,c=this.options,d=c.chart,g,e;b=this.renderTo;var q=a.uniqueKey(),m;b||(this.renderTo=b=d.renderTo);f(b)&&(this.renderTo=b=u.getElementById(b));b||a.error(13,!0);g=J(E(b,"data-highcharts-chart"));A(g)&&k[g]&&k[g].hasRendered&&k[g].destroy();E(b,"data-highcharts-chart",this.index);b.innerHTML="";d.skipClone||b.offsetWidth||this.cloneRenderTo();
this.getChartSize();g=this.chartWidth;e=this.chartHeight;m=H({position:"relative",overflow:"hidden",width:g+"px",height:e+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},d.style);this.container=b=n("div",{id:q},m,this.renderToClone||b);this._cursor=b.style.cursor;this.renderer=new (a[d.renderer]||R)(b,g,e,null,d.forExport,c.exporting&&c.exporting.allowHTML);this.setClassName(d.className);this.renderer.setStyle(d.style);this.renderer.chartIndex=this.index},
getMargins:function(a){var b=this.spacing,d=this.margin,f=this.titleOffset;this.resetMargins();f&&!c(d[0])&&(this.plotTop=Math.max(this.plotTop,f+this.options.title.margin+b[0]));this.legend.display&&this.legend.adjustMargins(d,b);this.extraMargin&&(this[this.extraMargin.type]=(this[this.extraMargin.type]||0)+this.extraMargin.value);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);a||this.getAxisMargins()},getAxisMargins:function(){var a=this,b=a.axisOffset=[0,0,0,0],d=a.margin;a.hasCartesianSeries&&
p(a.axes,function(a){a.visible&&a.getOffset()});p(G,function(f,g){c(d[g])||(a[f]+=b[g])});a.setChartSize()},reflow:function(a){var b=this,f=b.options.chart,g=b.renderTo,e=c(f.width),q=f.width||d(g,"width"),f=f.height||d(g,"height"),g=a?a.target:M;if(!e&&!b.isPrinting&&q&&f&&(g===M||g===u)){if(q!==b.containerWidth||f!==b.containerHeight)clearTimeout(b.reflowTimeout),b.reflowTimeout=S(function(){b.container&&b.setSize(void 0,void 0,!1)},a?100:0);b.containerWidth=q;b.containerHeight=f}},initReflow:function(){var a=
this,b;b=B(M,"resize",function(b){a.reflow(b)});B(a,"destroy",b)},setSize:function(b,c,d){var f=this,g=f.renderer;f.isResizing+=1;a.setAnimation(d,f);f.oldChartHeight=f.chartHeight;f.oldChartWidth=f.chartWidth;void 0!==b&&(f.options.chart.width=b);void 0!==c&&(f.options.chart.height=c);f.getChartSize();b=g.globalAnimation;(b?z:e)(f.container,{width:f.chartWidth+"px",height:f.chartHeight+"px"},b);f.setChartSize(!0);g.setSize(f.chartWidth,f.chartHeight,d);p(f.axes,function(a){a.isDirty=!0;a.setScale()});
f.isDirtyLegend=!0;f.isDirtyBox=!0;f.layOutTitles();f.getMargins();f.redraw(d);f.oldChartHeight=null;m(f,"resize");S(function(){f&&m(f,"endResize",null,function(){--f.isResizing})},C(b).duration)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,f=this.chartHeight,g=this.options.chart,e=this.spacing,q=this.clipOffset,k,m,h,x;this.plotLeft=k=Math.round(this.plotLeft);this.plotTop=m=Math.round(this.plotTop);this.plotWidth=h=Math.max(0,Math.round(d-k-this.marginRight));
this.plotHeight=x=Math.max(0,Math.round(f-m-this.marginBottom));this.plotSizeX=b?x:h;this.plotSizeY=b?h:x;this.plotBorderWidth=g.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:e[3],y:e[0],width:d-e[3]-e[1],height:f-e[0]-e[2]};this.plotBox=c.plotBox={x:k,y:m,width:h,height:x};d=2*Math.floor(this.plotBorderWidth/2);b=Math.ceil(Math.max(d,q[3])/2);c=Math.ceil(Math.max(d,q[0])/2);this.clipBox={x:b,y:c,width:Math.floor(this.plotSizeX-Math.max(d,q[1])/2-b),height:Math.max(0,Math.floor(this.plotSizeY-
Math.max(d,q[2])/2-c))};a||p(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this,b=a.options.chart;p(["margin","spacing"],function(c){var d=b[c],f=v(d)?d:[d,d,d,d];p(["Top","Right","Bottom","Left"],function(d,g){a[c][g]=x(b[c+d],f[g])})});p(G,function(b,c){a[b]=x(a.margin[c],a.spacing[c])});a.axisOffset=[0,0,0,0];a.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,f=this.chartBackground,
g=this.plotBackground,e=this.plotBorder,q,k=this.plotBGImage,m=a.backgroundColor,p=a.plotBackgroundColor,h=a.plotBackgroundImage,x,l=this.plotLeft,r=this.plotTop,n=this.plotWidth,v=this.plotHeight,t=this.plotBox,y=this.clipRect,u=this.clipBox,J="animate";f||(this.chartBackground=f=b.rect().addClass("highcharts-background").add(),J="attr");q=a.borderWidth||0;x=q+(a.shadow?8:0);m={fill:m||"none"};if(q||f["stroke-width"])m.stroke=a.borderColor,m["stroke-width"]=q;f.attr(m).shadow(a.shadow);f[J]({x:x/
2,y:x/2,width:c-x-q%2,height:d-x-q%2,r:a.borderRadius});J="animate";g||(J="attr",this.plotBackground=g=b.rect().addClass("highcharts-plot-background").add());g[J](t);g.attr({fill:p||"none"}).shadow(a.plotShadow);h&&(k?k.animate(t):this.plotBGImage=b.image(h,l,r,n,v).add());y?y.animate({width:u.width,height:u.height}):this.clipRect=b.clipRect(u);J="animate";e||(J="attr",this.plotBorder=e=b.rect().addClass("highcharts-plot-border").attr({zIndex:1}).add());e.attr({stroke:a.plotBorderColor,"stroke-width":a.plotBorderWidth||
0,fill:"none"});e[J](e.crisp({x:l,y:r,width:n,height:v},-e.strokeWidth()));this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,f,g;p(["inverted","angular","polar"],function(e){c=L[b.type||b.defaultSeriesType];g=b[e]||c&&c.prototype[e];for(f=d&&d.length;!g&&f--;)(c=L[d[f].type])&&c.prototype[e]&&(g=!0);a[e]=g})},linkSeries:function(){var a=this,b=a.series;p(b,function(a){a.linkedSeries.length=0});p(b,function(b){var c=b.options.linkedTo;f(c)&&(c=":previous"===
c?a.series[b.index-1]:a.get(c))&&c.linkedParent!==b&&(c.linkedSeries.push(b),b.linkedParent=c,b.visible=x(b.options.visible,c.options.visible,b.visible))})},renderSeries:function(){p(this.series,function(a){a.translate();a.render()})},renderLabels:function(){var a=this,b=a.options.labels;b.items&&p(b.items,function(c){var d=H(b.style,c.style),f=J(d.left)+a.plotLeft,g=J(d.top)+a.plotTop+12;delete d.left;delete d.top;a.renderer.text(c.html,f,g).attr({zIndex:2}).css(d).add()})},render:function(){var a=
this.axes,b=this.renderer,c=this.options,d,f,g;this.setTitle();this.legend=new y(this,c.legend);this.getStacks&&this.getStacks();this.getMargins(!0);this.setChartSize();c=this.plotWidth;d=this.plotHeight-=21;p(a,function(a){a.setScale()});this.getAxisMargins();f=1.1<c/this.plotWidth;g=1.05<d/this.plotHeight;if(f||g)p(a,function(a){(a.horiz&&f||!a.horiz&&g)&&a.setTickInterval(!0)}),this.getMargins();this.drawChartBox();this.hasCartesianSeries&&p(a,function(a){a.visible&&a.render()});this.seriesGroup||
(this.seriesGroup=b.g("series-group").attr({zIndex:3}).add());this.renderSeries();this.renderLabels();this.addCredits();this.setResponsive&&this.setResponsive();this.hasRendered=!0},addCredits:function(a){var b=this;a=F(!0,this.options.credits,a);a.enabled&&!this.credits&&(this.credits=this.renderer.text(a.text+(this.mapCredits||""),0,0).addClass("highcharts-credits").on("click",function(){a.href&&(M.location.href=a.href)}).attr({align:a.position.align,zIndex:8}).css(a.style).add().align(a.position),
this.credits.update=function(a){b.credits=b.credits.destroy();b.addCredits(a)})},destroy:function(){var b=this,c=b.axes,d=b.series,f=b.container,g,e=f&&f.parentNode;m(b,"destroy");k[b.index]=void 0;a.chartCount--;b.renderTo.removeAttribute("data-highcharts-chart");K(b);for(g=c.length;g--;)c[g]=c[g].destroy();this.scroller&&this.scroller.destroy&&this.scroller.destroy();for(g=d.length;g--;)d[g]=d[g].destroy();p("title subtitle chartBackground plotBackground plotBGImage plotBorder seriesGroup clipRect credits pointer rangeSelector legend resetZoomButton tooltip renderer".split(" "),
function(a){var c=b[a];c&&c.destroy&&(b[a]=c.destroy())});f&&(f.innerHTML="",K(f),e&&l(f));for(g in b)delete b[g]},isReadyToRender:function(){var a=this;return D||M!=M.top||"complete"===u.readyState?!0:(u.attachEvent("onreadystatechange",function(){u.detachEvent("onreadystatechange",a.firstRender);"complete"===u.readyState&&a.firstRender()}),!1)},firstRender:function(){var a=this,b=a.options;if(a.isReadyToRender()){a.getContainer();m(a,"init");a.resetMargins();a.setChartSize();a.propFromSeries();
a.getAxes();p(b.series||[],function(b){a.initSeries(b)});a.linkSeries();m(a,"beforeRender");q&&(a.pointer=new q(a,b));a.render();if(!a.renderer.imgCount&&a.onload)a.onload();a.cloneRenderTo(!0)}},onload:function(){p([this.callback].concat(this.callbacks),function(a){a&&void 0!==this.index&&a.apply(this,[this])},this);m(this,"load");m(this,"render");c(this.index)&&!1!==this.options.chart.reflow&&this.initReflow();this.onload=null}}})(I);(function(a){var B,z=a.each,C=a.extend,E=a.erase,u=a.fireEvent,
h=a.format,n=a.isArray,t=a.isNumber,l=a.pick,k=a.removeEvent;B=a.Point=function(){};B.prototype={init:function(a,c,k){this.series=a;this.color=a.color;this.applyOptions(c,k);a.options.colorByPoint?(c=a.options.colors||a.chart.options.colors,this.color=this.color||c[a.colorCounter],c=c.length,k=a.colorCounter,a.colorCounter++,a.colorCounter===c&&(a.colorCounter=0)):k=a.colorIndex;this.colorIndex=l(this.colorIndex,k);a.chart.pointCount++;return this},applyOptions:function(a,c){var e=this.series,k=e.options.pointValKey||
e.pointValKey;a=B.prototype.optionsToObject.call(this,a);C(this,a);this.options=this.options?C(this.options,a):a;a.group&&delete this.group;k&&(this.y=this[k]);this.isNull=l(this.isValid&&!this.isValid(),null===this.x||!t(this.y,!0));this.selected&&(this.state="select");"name"in this&&void 0===c&&e.xAxis&&e.xAxis.hasNames&&(this.x=e.xAxis.nameToX(this));void 0===this.x&&e&&(this.x=void 0===c?e.autoIncrement(this):c);return this},optionsToObject:function(a){var c={},e=this.series,k=e.options.keys,
b=k||e.pointArrayMap||["y"],m=b.length,d=0,h=0;if(t(a)||null===a)c[b[0]]=a;else if(n(a))for(!k&&a.length>m&&(e=typeof a[0],"string"===e?c.name=a[0]:"number"===e&&(c.x=a[0]),d++);h<m;)k&&void 0===a[d]||(c[b[h]]=a[d]),d++,h++;else"object"===typeof a&&(c=a,a.dataLabels&&(e._hasPointLabels=!0),a.marker&&(e._hasPointMarkers=!0));return c},getClassName:function(){return"highcharts-point"+(this.selected?" highcharts-point-select":"")+(this.negative?" highcharts-negative":"")+(this.isNull?" highcharts-null-point":
"")+(void 0!==this.colorIndex?" highcharts-color-"+this.colorIndex:"")+(this.options.className?" "+this.options.className:"")+(this.zone&&this.zone.className?" "+this.zone.className.replace("highcharts-negative",""):"")},getZone:function(){var a=this.series,c=a.zones,a=a.zoneAxis||"y",k=0,h;for(h=c[k];this[a]>=h.value;)h=c[++k];h&&h.color&&!this.options.color&&(this.color=h.color);return h},destroy:function(){var a=this.series.chart,c=a.hoverPoints,h;a.pointCount--;c&&(this.setState(),E(c,this),c.length||
(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)k(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(h in this)this[h]=null},destroyElements:function(){for(var a=["graphic","dataLabel","dataLabelUpper","connector","shadowGroup"],c,k=6;k--;)c=a[k],this[c]&&(this[c]=this[c].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,
point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var c=this.series,e=c.tooltipOptions,k=l(e.valueDecimals,""),b=e.valuePrefix||"",m=e.valueSuffix||"";z(c.pointArrayMap||["y"],function(c){c="{point."+c;if(b||m)a=a.replace(c+"}",b+c+"}"+m);a=a.replace(c+"}",c+":,."+k+"f}")});return h(a,{point:this,series:this.series})},firePointEvent:function(a,c,k){var e=this,b=this.series.options;(b.point.events[a]||e.options&&e.options.events&&e.options.events[a])&&
this.importEvents();"click"===a&&b.allowPointSelect&&(k=function(a){e.select&&e.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});u(this,a,c,k)},visible:!0}})(I);(function(a){var B=a.addEvent,z=a.animObject,C=a.arrayMax,E=a.arrayMin,u=a.correctFloat,h=a.Date,n=a.defaultOptions,t=a.defaultPlotOptions,l=a.defined,k=a.each,e=a.erase,c=a.extend,p=a.fireEvent,H=a.grep,b=a.isArray,m=a.isNumber,d=a.isString,r=a.merge,A=a.pick,v=a.removeEvent,f=a.splat,y=a.SVGElement,G=a.syncTimeout,F=a.win;a.Series=a.seriesType("line",
null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",
x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3},{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var d=this,f,e,g=a.series,q;d.chart=a;d.options=b=d.setOptions(b);d.linkedSeries=[];d.bindAxes();c(d,{name:b.name,
state:"",visible:!1!==b.visible,selected:!0===b.selected});e=b.events;for(f in e)B(d,f,e[f]);if(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;d.getColor();d.getSymbol();k(d.parallelArrays,function(a){d[a+"Data"]=[]});d.setData(b.data,!1);d.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(q=g[g.length-1]);d._i=A(q&&q._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var b=this.options.index,c;if(m(b)){for(c=a.length;c--;)if(b>=A(a[c].options.index,
a[c]._i)){a.splice(c+1,0,this);break}-1===c&&a.unshift(this);c+=1}else a.push(this);return A(c,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,f;k(b.axisTypes||[],function(e){k(d[e],function(a){f=a.options;if(c[e]===f.index||void 0!==c[e]&&c[e]===f.id||void 0===c[e]&&0===f.index)b.insert(a.series),b[e]=a,a.isDirty=!0});b[e]||b.optionalAxis===e||a.error(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,d=arguments,f=m(b)?function(d){var f="y"===d&&c.toYData?c.toYData(a):
a[d];c[d+"Data"][b]=f}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d,2))};k(c.parallelArrays,f)},autoIncrement:function(){var a=this.options,b=this.xIncrement,c,d=a.pointIntervalUnit,b=A(b,a.pointStart,0);this.pointInterval=c=A(this.pointInterval,a.pointInterval,1);d&&(a=new h(b),"day"===d?a=+a[h.hcSetDate](a[h.hcGetDate]()+c):"month"===d?a=+a[h.hcSetMonth](a[h.hcGetMonth]()+c):"year"===d&&(a=+a[h.hcSetFullYear](a[h.hcGetFullYear]()+c)),c=a-b);this.xIncrement=b+c;return b},
setOptions:function(a){var b=this.chart,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},f=c[this.type];this.userOptions=a;c=r(f,c.series,a);this.tooltipOptions=r(n.tooltip,n.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip);null===f.marker&&delete c.marker;this.zoneAxis=c.zoneAxis;a=this.zones=(c.zones||[]).slice();!c.negativeColor&&!c.negativeFillColor||c.zones||a.push({value:c[this.zoneAxis+"Threshold"]||c.threshold||
0,className:"highcharts-negative",color:c.negativeColor,fillColor:c.negativeFillColor});a.length&&l(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return c},getCyclic:function(a,b,c){var d,f=this.chart,g=this.userOptions,e=a+"Index",q=a+"Counter",k=c?c.length:A(f.options.chart[a+"Count"],f[a+"Count"]);b||(d=A(g[e],g["_"+e]),l(d)||(f.series.length||(f[q]=0),g["_"+e]=d=f[q]%k,f[q]+=1),c&&(b=c[d]));void 0!==d&&(this[e]=d);this[a]=b},getColor:function(){this.options.colorByPoint?
this.options.color=null:this.getCyclic("color",this.options.color||t[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(c,f,e,h){var q=this,g=q.points,p=g&&g.length||0,l,x=q.options,r=q.chart,n=null,v=q.xAxis,t=x.turboThreshold,y=this.xData,u=this.yData,G=(l=q.pointArrayMap)&&l.length;c=c||[];l=c.length;f=A(f,!0);if(!1!==h&&l&&p===l&&!q.cropped&&
!q.hasGroupedData&&q.visible)k(c,function(a,b){g[b].update&&a!==x.data[b]&&g[b].update(a,!1,null,!1)});else{q.xIncrement=null;q.colorCounter=0;k(this.parallelArrays,function(a){q[a+"Data"].length=0});if(t&&l>t){for(e=0;null===n&&e<l;)n=c[e],e++;if(m(n))for(e=0;e<l;e++)y[e]=this.autoIncrement(),u[e]=c[e];else if(b(n))if(G)for(e=0;e<l;e++)n=c[e],y[e]=n[0],u[e]=n.slice(1,G+1);else for(e=0;e<l;e++)n=c[e],y[e]=n[0],u[e]=n[1];else a.error(12)}else for(e=0;e<l;e++)void 0!==c[e]&&(n={series:q},q.pointClass.prototype.applyOptions.apply(n,
[c[e]]),q.updateParallelArrays(n,e));d(u[0])&&a.error(14,!0);q.data=[];q.options.data=q.userOptions.data=c;for(e=p;e--;)g[e]&&g[e].destroy&&g[e].destroy();v&&(v.minRange=v.userMinRange);q.isDirty=r.isDirtyBox=!0;q.isDirtyData=!!g;e=!1}"point"===x.legendType&&(this.processData(),this.generatePoints());f&&r.redraw(e)},processData:function(b){var c=this.xData,d=this.yData,f=c.length,e;e=0;var g,q,k=this.xAxis,m,h=this.options;m=h.cropThreshold;var l=this.getExtremesFromAll||h.getExtremesFromAll,p=this.isCartesian,
h=k&&k.val2lin,n=k&&k.isLog,r,v;if(p&&!this.isDirty&&!k.isDirty&&!this.yAxis.isDirty&&!b)return!1;k&&(b=k.getExtremes(),r=b.min,v=b.max);if(p&&this.sorted&&!l&&(!m||f>m||this.forceCrop))if(c[f-1]<r||c[0]>v)c=[],d=[];else if(c[0]<r||c[f-1]>v)e=this.cropData(this.xData,this.yData,r,v),c=e.xData,d=e.yData,e=e.start,g=!0;for(m=c.length||1;--m;)f=n?h(c[m])-h(c[m-1]):c[m]-c[m-1],0<f&&(void 0===q||f<q)?q=f:0>f&&this.requireSorting&&a.error(15);this.cropped=g;this.cropStart=e;this.processedXData=c;this.processedYData=
d;this.closestPointRange=q},cropData:function(a,b,c,d){var f=a.length,g=0,e=f,q=A(this.cropShoulder,1),k;for(k=0;k<f;k++)if(a[k]>=c){g=Math.max(0,k-q);break}for(c=k;c<f;c++)if(a[c]>d){e=c+q;break}return{xData:a.slice(g,e),yData:b.slice(g,e),start:g,end:e}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,g=this.pointClass,k=d.length,m=this.cropStart||0,h,l=this.hasGroupedData,p,n=[],r;b||l||(b=[],b.length=a.length,b=this.data=b);for(r=0;r<
k;r++)h=m+r,l?(p=(new g).init(this,[d[r]].concat(f(e[r]))),p.dataGroup=this.groupMap[r]):(p=b[h])||void 0===a[h]||(b[h]=p=(new g).init(this,a[h],d[r])),p.index=h,n[r]=p;if(b&&(k!==(c=b.length)||l))for(r=0;r<c;r++)r!==m||l||(r+=k),b[r]&&(b[r].destroyElements(),b[r].plotX=void 0);this.data=b;this.points=n},getExtremes:function(a){var c=this.yAxis,d=this.processedXData,f,e=[],g=0;f=this.xAxis.getExtremes();var q=f.min,k=f.max,h,l,p,r;a=a||this.stackedYData||this.processedYData||[];f=a.length;for(r=0;r<
f;r++)if(l=d[r],p=a[r],h=(m(p,!0)||b(p))&&(!c.positiveValuesOnly||p.length||0<p),l=this.getExtremesFromAll||this.options.getExtremesFromAll||this.cropped||(d[r+1]||l)>=q&&(d[r-1]||l)<=k,h&&l)if(h=p.length)for(;h--;)null!==p[h]&&(e[g++]=p[h]);else e[g++]=p;this.dataMin=E(e);this.dataMax=C(e)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,f=this.yAxis,e=this.points,k=e.length,h=!!this.modifyValue,p=a.pointPlacement,
r="between"===p||m(p),n=a.threshold,v=a.startFromThreshold?n:0,t,y,G,F,H=Number.MAX_VALUE;"between"===p&&(p=.5);m(p)&&(p*=A(a.pointRange||c.pointRange));for(a=0;a<k;a++){var z=e[a],B=z.x,C=z.y;y=z.low;var E=b&&f.stacks[(this.negStacks&&C<(v?0:n)?"-":"")+this.stackKey],I;f.positiveValuesOnly&&null!==C&&0>=C&&(z.isNull=!0);z.plotX=t=u(Math.min(Math.max(-1E5,c.translate(B,0,0,0,1,p,"flags"===this.type)),1E5));b&&this.visible&&!z.isNull&&E&&E[B]&&(F=this.getStackIndicator(F,B,this.index),I=E[B],C=I.points[F.key],
y=C[0],C=C[1],y===v&&F.key===E[B].base&&(y=A(n,f.min)),f.positiveValuesOnly&&0>=y&&(y=null),z.total=z.stackTotal=I.total,z.percentage=I.total&&z.y/I.total*100,z.stackY=C,I.setOffset(this.pointXOffset||0,this.barW||0));z.yBottom=l(y)?f.translate(y,0,1,0,1):null;h&&(C=this.modifyValue(C,z));z.plotY=y="number"===typeof C&&Infinity!==C?Math.min(Math.max(-1E5,f.translate(C,0,1,0,1)),1E5):void 0;z.isInside=void 0!==y&&0<=y&&y<=f.len&&0<=t&&t<=c.len;z.clientX=r?u(c.translate(B,0,0,0,1,p)):t;z.negative=z.y<
(n||0);z.category=d&&void 0!==d[z.x]?d[z.x]:z.x;z.isNull||(void 0!==G&&(H=Math.min(H,Math.abs(t-G))),G=t);z.zone=this.zones.length&&z.getZone()}this.closestPointRangePx=H},getValidPoints:function(a,b){var c=this.chart;return H(a||this.points||[],function(a){return b&&!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,f=b.inverted,e=this.clipBox,q=e||b.clipBox,k=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,q.height,
c.xAxis,c.yAxis].join(),m=b[k],h=b[k+"m"];m||(a&&(q.width=0,b[k+"m"]=h=d.clipRect(-99,f?-b.plotLeft:-b.plotTop,99,f?b.chartWidth:b.chartHeight)),b[k]=m=d.clipRect(q),m.count={length:0});a&&!m.count[this.index]&&(m.count[this.index]=!0,m.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?m:b.clipRect),this.markerGroup.clip(h),this.sharedClipKey=k);a||(m.count[this.index]&&(delete m.count[this.index],--m.count.length),0===m.count.length&&k&&b[k]&&(e||(b[k]=b[k].destroy()),b[k+"m"]&&(this.markerGroup.clip(),
b[k+"m"]=b[k+"m"].destroy())))},animate:function(a){var b=this.chart,c=z(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip();p(this,"afterAnimate")},drawPoints:function(){var a=this.points,b=this.chart,c,d,f,e,k=this.options.marker,h,p,l,r,n=this.markerGroup,v=A(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);
if(!1!==k.enabled||this._hasPointMarkers)for(d=0;d<a.length;d++)f=a[d],c=f.plotY,e=f.graphic,h=f.marker||{},p=!!f.marker,l=v&&void 0===h.enabled||h.enabled,r=f.isInside,l&&m(c)&&null!==f.y?(c=A(h.symbol,this.symbol),f.hasImage=0===c.indexOf("url"),l=this.markerAttribs(f,f.selected&&"select"),e?e[r?"show":"hide"](!0).animate(l):r&&(0<l.width||f.hasImage)&&(f.graphic=e=b.renderer.symbol(c,l.x,l.y,l.width,l.height,p?h:k).add(n)),e&&e.attr(this.pointAttribs(f,f.selected&&"select")),e&&e.addClass(f.getClassName(),
!0)):e&&(f.graphic=e.destroy())},markerAttribs:function(a,b){var c=this.options.marker,d=a.marker||{},f=A(d.radius,c.radius);b&&(c=c.states[b],b=d.states&&d.states[b],f=A(b&&b.radius,c&&c.radius,f+(c&&c.radiusPlus||0)));a.hasImage&&(f=0);a={x:Math.floor(a.plotX)-f,y:a.plotY-f};f&&(a.width=a.height=2*f);return a},pointAttribs:function(a,b){var c=this.options.marker,d=a&&a.options,f=d&&d.marker||{},e=this.color,q=d&&d.color,k=a&&a.color,d=A(f.lineWidth,c.lineWidth);a=a&&a.zone&&a.zone.color;e=q||a||
k||e;a=f.fillColor||c.fillColor||e;e=f.lineColor||c.lineColor||e;b&&(c=c.states[b],b=f.states&&f.states[b]||{},d=A(b.lineWidth,c.lineWidth,d+A(b.lineWidthPlus,c.lineWidthPlus,0)),a=b.fillColor||c.fillColor||a,e=b.lineColor||c.lineColor||e);return{stroke:e,"stroke-width":d,fill:a}},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(F.navigator.userAgent),d,f=a.data||[],g,m,h;p(a,"destroy");v(a);k(a.axisTypes||[],function(b){(h=a[b])&&h.series&&(e(h.series,a),h.isDirty=h.forceRedraw=
!0)});a.legendItem&&a.chart.legend.destroyItem(a);for(d=f.length;d--;)(g=f[d])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);for(m in a)a[m]instanceof y&&!a[m].survive&&(d=c&&"group"===m?"hide":"destroy",a[m][d]());b.hoverSeries===a&&(b.hoverSeries=null);e(b.series,a);b.orderSeries();for(m in a)delete a[m]},getGraphPath:function(a,b,c){var d=this,f=d.options,e=f.step,q,m=[],h=[],p;a=a||d.points;(q=a.reversed)&&a.reverse();(e={right:1,center:2}[e]||e&&3)&&q&&(e=4-e);!f.connectNulls||
b||c||(a=this.getValidPoints(a));k(a,function(g,k){var q=g.plotX,r=g.plotY,n=a[k-1];(g.leftCliff||n&&n.rightCliff)&&!c&&(p=!0);g.isNull&&!l(b)&&0<k?p=!f.connectNulls:g.isNull&&!b?p=!0:(0===k||p?k=["M",g.plotX,g.plotY]:d.getPointSpline?k=d.getPointSpline(a,g,k):e?(k=1===e?["L",n.plotX,r]:2===e?["L",(n.plotX+q)/2,n.plotY,"L",(n.plotX+q)/2,r]:["L",q,n.plotY],k.push("L",q,r)):k=["L",q,r],h.push(g.x),e&&h.push(g.x),m.push.apply(m,k),p=!1)});m.xMap=h;return d.graphPath=m},drawGraph:function(){var a=this,
b=this.options,c=(this.gappedPath||this.getGraphPath).call(this),d=[["graph","highcharts-graph",b.lineColor||this.color,b.dashStyle]];k(this.zones,function(c,f){d.push(["zone-graph-"+f,"highcharts-graph highcharts-zone-graph-"+f+" "+(c.className||""),c.color||a.color,c.dashStyle||b.dashStyle])});k(d,function(d,f){var e=d[0],g=a[e];g?(g.endX=c.xMap,g.animate({d:c})):c.length&&(a[e]=a.chart.renderer.path(c).addClass(d[1]).attr({zIndex:1}).add(a.group),g={stroke:d[2],"stroke-width":b.lineWidth,fill:a.fillGraph&&
a.color||"none"},d[3]?g.dashstyle=d[3]:"square"!==b.linecap&&(g["stroke-linecap"]=g["stroke-linejoin"]="round"),g=a[e].attr(g).shadow(2>f&&b.shadow));g&&(g.startX=c.xMap,g.isArea=c.isArea)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,f,e,m=this.clips||[],h,p=this.graph,l=this.area,r=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],v,t,y=b.inverted,u,G,F,H,z=!1;d.length&&(p||l)&&n&&void 0!==n.min&&(t=n.reversed,u=n.horiz,p&&p.hide(),l&&l.hide(),
v=n.getExtremes(),k(d,function(d,g){f=t?u?b.plotWidth:0:u?0:n.toPixels(v.min);f=Math.min(Math.max(A(e,f),0),r);e=Math.min(Math.max(Math.round(n.toPixels(A(d.value,v.max),!0)),0),r);z&&(f=e=n.toPixels(v.max));G=Math.abs(f-e);F=Math.min(f,e);H=Math.max(f,e);n.isXAxis?(h={x:y?H:F,y:0,width:G,height:r},u||(h.x=b.plotHeight-h.x)):(h={x:0,y:y?H:F,width:r,height:G},u&&(h.y=b.plotWidth-h.y));y&&c.isVML&&(h=n.isXAxis?{x:0,y:t?F:H,height:h.width,width:b.chartWidth}:{x:h.y-b.plotLeft-b.spacingBox.x,y:0,width:h.height,
height:b.chartHeight});m[g]?m[g].animate(h):(m[g]=c.clipRect(h),p&&a["zone-graph-"+g].clip(m[g]),l&&a["zone-area-"+g].clip(m[g]));z=d.value>v.max}),this.clips=m)},invertGroups:function(a){function b(){k(["group","markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,f;c.xAxis&&(f=B(d,"resize",b),B(c,"destroy",f),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,f){var e=
this[a],k=!e;k&&(this[a]=e=this.chart.renderer.g(b).attr({zIndex:d||.1}).add(f),e.addClass("highcharts-series-"+this.index+" highcharts-"+this.type+"-series highcharts-color-"+this.colorIndex+" "+(this.options.className||"")));e.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return e},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=
this,b=a.chart,c,d=a.options,f=!!a.animate&&b.renderer.isSVG&&z(d.animation).duration,e=a.visible?"inherit":"hidden",k=d.zIndex,m=a.hasRendered,h=b.seriesGroup,p=b.inverted;c=a.plotGroup("group","series",e,k,h);a.markerGroup=a.plotGroup("markerGroup","markers",e,k,h);f&&a.animate(!0);c.inverted=a.isCartesian?p:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(p);
!1===d.clip||a.sharedClipKey||m||c.clip(b.clipRect);f&&a.animate();m||(a.animationTimeout=G(function(){a.afterAnimate()},f));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,f=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:A(d&&d.left,a.plotLeft),translateY:A(f&&f.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdDimensions:1,kdAxisArray:["clientX",
"plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,f=this.chart.inverted;return this.searchKDTree({clientX:f?c.len-a.chartY+c.pos:a.chartX-c.pos,plotY:f?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,f){var e,g;if(g=c&&c.length)return e=b.kdAxisArray[d%f],c.sort(function(a,b){return a[e]-b[e]}),g=Math.floor(g/2),{point:c[g],left:a(c.slice(0,g),d+1,f),right:a(c.slice(g+1),d+1,f)}}this.buildingKdTree=!0;var b=this,c=b.kdDimensions;delete b.kdTree;G(function(){b.kdTree=
a(b.getValidPoints(null,!b.directTouch),c,c);b.buildingKdTree=!1},b.options.kdNow?0:1)},searchKDTree:function(a,b){function c(a,b,g,m){var h=b.point,p=d.kdAxisArray[g%m],q,r,n=h;r=l(a[f])&&l(h[f])?Math.pow(a[f]-h[f],2):null;q=l(a[e])&&l(h[e])?Math.pow(a[e]-h[e],2):null;q=(r||0)+(q||0);h.dist=l(q)?Math.sqrt(q):Number.MAX_VALUE;h.distX=l(r)?Math.sqrt(r):Number.MAX_VALUE;p=a[p]-h[p];q=0>p?"left":"right";r=0>p?"right":"left";b[q]&&(q=c(a,b[q],g+1,m),n=q[k]<n[k]?q:h);b[r]&&Math.sqrt(p*p)<n[k]&&(a=c(a,
b[r],g+1,m),n=a[k]<n[k]?a:n);return n}var d=this,f=this.kdAxisArray[0],e=this.kdAxisArray[1],k=b?"distX":"dist";this.kdTree||this.buildingKdTree||this.buildKDTree();if(this.kdTree)return c(a,this.kdTree,this.kdDimensions,this.kdDimensions)}})})(I);(function(a){function B(a,e,c,h,n){var b=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=e;this.x=h;this.total=null;this.points={};this.stack=n;this.rightCliff=this.leftCliff=0;this.alignOptions={align:e.align||(b?c?"left":"right":"center"),
verticalAlign:e.verticalAlign||(b?"middle":c?"bottom":"top"),y:l(e.y,b?4:c?14:-6),x:l(e.x,b?c?-6:6:0)};this.textAlign=e.textAlign||(b?c?"right":"left":"center")}var z=a.Axis,C=a.Chart,E=a.correctFloat,u=a.defined,h=a.destroyObjectProperties,n=a.each,t=a.format,l=a.pick;a=a.Series;B.prototype={destroy:function(){h(this,this.axis)},render:function(a){var e=this.options,c=e.format,c=c?t(c,this):e.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,
null,null,e.useHTML).css(e.style).attr({align:this.textAlign,rotation:e.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,e){var c=this.axis,k=c.chart,h=k.inverted,b=c.reversed,b=this.isNegative&&!b||!this.isNegative&&b,m=c.translate(c.usePercentage?100:this.total,0,0,0,1),c=c.translate(0),c=Math.abs(m-c);a=k.xAxis[0].translate(this.x)+a;var d=k.plotHeight,h={x:h?b?m:m-c:a,y:h?d-a-e:b?d-m-c:d-m,width:h?c:e,height:h?e:c};if(e=this.label)e.align(this.alignOptions,null,h),h=e.alignAttr,e[!1===
this.options.crop||k.isInsidePlot(h.x,h.y)?"show":"hide"](!0)}};C.prototype.getStacks=function(){var a=this;n(a.yAxis,function(a){a.stacks&&a.hasVisibleSeries&&(a.oldStacks=a.stacks)});n(a.series,function(e){!e.options.stacking||!0!==e.visible&&!1!==a.options.chart.ignoreHiddenSeries||(e.stackKey=e.type+l(e.options.stack,""))})};z.prototype.buildStacks=function(){var a=this.series,e,c=l(this.options.reversedStacks,!0),h=a.length,n;if(!this.isXAxis){this.usePercentage=!1;for(n=h;n--;)a[c?n:h-n-1].setStackedPoints();
for(n=h;n--;)e=a[c?n:h-n-1],e.setStackCliffs&&e.setStackCliffs();if(this.usePercentage)for(n=0;n<h;n++)a[n].setPercentStacks()}};z.prototype.renderStackTotals=function(){var a=this.chart,e=a.renderer,c=this.stacks,h,l,b=this.stackTotalGroup;b||(this.stackTotalGroup=b=e.g("stack-labels").attr({visibility:"visible",zIndex:6}).add());b.translate(a.plotLeft,a.plotTop);for(h in c)for(l in a=c[h],a)a[l].render(b)};z.prototype.resetStacks=function(){var a=this.stacks,e,c;if(!this.isXAxis)for(e in a)for(c in a[e])a[e][c].touched<
this.stacksTouched?(a[e][c].destroy(),delete a[e][c]):(a[e][c].total=null,a[e][c].cum=null)};z.prototype.cleanStacks=function(){var a,e,c;if(!this.isXAxis)for(e in this.oldStacks&&(a=this.stacks=this.oldStacks),a)for(c in a[e])a[e][c].cum=a[e][c].total};a.prototype.setStackedPoints=function(){if(this.options.stacking&&(!0===this.visible||!1===this.chart.options.chart.ignoreHiddenSeries)){var a=this.processedXData,e=this.processedYData,c=[],h=e.length,n=this.options,b=n.threshold,m=n.startFromThreshold?
b:0,d=n.stack,n=n.stacking,r=this.stackKey,t="-"+r,v=this.negStacks,f=this.yAxis,y=f.stacks,G=f.oldStacks,F,q,x,z,K,C,g;f.stacksTouched+=1;for(K=0;K<h;K++)C=a[K],g=e[K],F=this.getStackIndicator(F,C,this.index),z=F.key,x=(q=v&&g<(m?0:b))?t:r,y[x]||(y[x]={}),y[x][C]||(G[x]&&G[x][C]?(y[x][C]=G[x][C],y[x][C].total=null):y[x][C]=new B(f,f.options.stackLabels,q,C,d)),x=y[x][C],null!==g&&(x.points[z]=x.points[this.index]=[l(x.cum,m)],u(x.cum)||(x.base=z),x.touched=f.stacksTouched,0<F.index&&!1===this.singleStacks&&
(x.points[z][0]=x.points[this.index+","+C+",0"][0])),"percent"===n?(q=q?r:t,v&&y[q]&&y[q][C]?(q=y[q][C],x.total=q.total=Math.max(q.total,x.total)+Math.abs(g)||0):x.total=E(x.total+(Math.abs(g)||0))):x.total=E(x.total+(g||0)),x.cum=l(x.cum,m)+(g||0),null!==g&&(x.points[z].push(x.cum),c[K]=x.cum);"percent"===n&&(f.usePercentage=!0);this.stackedYData=c;f.oldStacks={}}};a.prototype.setPercentStacks=function(){var a=this,e=a.stackKey,c=a.yAxis.stacks,h=a.processedXData,l;n([e,"-"+e],function(b){for(var e=
h.length,d,k;e--;)if(d=h[e],l=a.getStackIndicator(l,d,a.index,b),d=(k=c[b]&&c[b][d])&&k.points[l.key])k=k.total?100/k.total:0,d[0]=E(d[0]*k),d[1]=E(d[1]*k),a.stackedYData[e]=d[1]})};a.prototype.getStackIndicator=function(a,e,c,h){!u(a)||a.x!==e||h&&a.key!==h?a={x:e,index:0,key:h}:a.index++;a.key=[c,e,a.index].join();return a}})(I);(function(a){var B=a.addEvent,z=a.animate,C=a.Axis,E=a.createElement,u=a.css,h=a.defined,n=a.each,t=a.erase,l=a.extend,k=a.fireEvent,e=a.inArray,c=a.isNumber,p=a.isObject,
H=a.merge,b=a.pick,m=a.Point,d=a.Series,r=a.seriesTypes,A=a.setAnimation,v=a.splat;l(a.Chart.prototype,{addSeries:function(a,c,d){var f,e=this;a&&(c=b(c,!0),k(e,"addSeries",{options:a},function(){f=e.initSeries(a);e.isDirtyLegend=!0;e.linkSeries();c&&e.redraw(d)}));return f},addAxis:function(a,c,d,e){var f=c?"xAxis":"yAxis",h=this.options;a=H(a,{index:this[f].length,isX:c});new C(this,a);h[f]=v(h[f]||{});h[f].push(a);b(d,!0)&&this.redraw(e)},showLoading:function(a){var b=this,c=b.options,d=b.loadingDiv,
f=c.loading,e=function(){d&&u(d,{left:b.plotLeft+"px",top:b.plotTop+"px",width:b.plotWidth+"px",height:b.plotHeight+"px"})};d||(b.loadingDiv=d=E("div",{className:"highcharts-loading highcharts-loading-hidden"},null,b.container),b.loadingSpan=E("span",{className:"highcharts-loading-inner"},null,d),B(b,"redraw",e));d.className="highcharts-loading";b.loadingSpan.innerHTML=a||c.lang.loading;u(d,l(f.style,{zIndex:10}));u(b.loadingSpan,f.labelStyle);b.loadingShown||(u(d,{opacity:0,display:""}),z(d,{opacity:f.style.opacity||
.5},{duration:f.showDuration||0}));b.loadingShown=!0;e()},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&(b.className="highcharts-loading highcharts-loading-hidden",z(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){u(b,{display:"none"})}}));this.loadingShown=!1},propsRequireDirtyBox:"backgroundColor borderColor borderWidth margin marginTop marginRight marginBottom marginLeft spacing spacingTop spacingRight spacingBottom spacingLeft borderRadius plotBackgroundColor plotBackgroundImage plotBorderColor plotBorderWidth plotShadow shadow".split(" "),
propsRequireUpdateSeries:"chart.inverted chart.polar chart.ignoreHiddenSeries chart.type colors plotOptions".split(" "),update:function(a,d){var f,k={credits:"addCredits",title:"setTitle",subtitle:"setSubtitle"},m=a.chart,l,p;if(m){H(!0,this.options.chart,m);"className"in m&&this.setClassName(m.className);if("inverted"in m||"polar"in m)this.propFromSeries(),l=!0;for(f in m)m.hasOwnProperty(f)&&(-1!==e("chart."+f,this.propsRequireUpdateSeries)&&(p=!0),-1!==e(f,this.propsRequireDirtyBox)&&(this.isDirtyBox=
!0));"style"in m&&this.renderer.setStyle(m.style)}for(f in a){if(this[f]&&"function"===typeof this[f].update)this[f].update(a[f],!1);else if("function"===typeof this[k[f]])this[k[f]](a[f]);"chart"!==f&&-1!==e(f,this.propsRequireUpdateSeries)&&(p=!0)}a.colors&&(this.options.colors=a.colors);a.plotOptions&&H(!0,this.options.plotOptions,a.plotOptions);n(["xAxis","yAxis","series"],function(b){a[b]&&n(v(a[b]),function(a,c){(c=h(a.id)&&this.get(a.id)||this[b][c])&&c.coll===b&&c.update(a,!1)},this)},this);
l&&n(this.axes,function(a){a.update({},!1)});p&&n(this.series,function(a){a.update({},!1)});a.loading&&H(!0,this.options.loading,a.loading);f=m&&m.width;m=m&&m.height;c(f)&&f!==this.chartWidth||c(m)&&m!==this.chartHeight?this.setSize(f,m):b(d,!0)&&this.redraw()},setSubtitle:function(a){this.setTitle(void 0,a)}});l(m.prototype,{update:function(a,c,d,e){function f(){h.applyOptions(a);null===h.y&&k&&(h.graphic=k.destroy());p(a,!0)&&(k&&k.element&&a&&a.marker&&a.marker.symbol&&(h.graphic=k.destroy()),
a&&a.dataLabels&&h.dataLabel&&(h.dataLabel=h.dataLabel.destroy()));l=h.index;m.updateParallelArrays(h,l);n.data[l]=p(n.data[l],!0)||p(a,!0)?h.options:a;m.isDirty=m.isDirtyData=!0;!m.fixedBox&&m.hasCartesianSeries&&(g.isDirtyBox=!0);"point"===n.legendType&&(g.isDirtyLegend=!0);c&&g.redraw(d)}var h=this,m=h.series,k=h.graphic,l,g=m.chart,n=m.options;c=b(c,!0);!1===e?f():h.firePointEvent("update",{options:a},f)},remove:function(a,b){this.series.removePoint(e(this,this.series.data),a,b)}});l(d.prototype,
{addPoint:function(a,c,d,e){var f=this.options,h=this.data,m=this.chart,k=this.xAxis,k=k&&k.hasNames&&k.names,l=f.data,g,p,n=this.xData,r,v;c=b(c,!0);g={series:this};this.pointClass.prototype.applyOptions.apply(g,[a]);v=g.x;r=n.length;if(this.requireSorting&&v<n[r-1])for(p=!0;r&&n[r-1]>v;)r--;this.updateParallelArrays(g,"splice",r,0,0);this.updateParallelArrays(g,r);k&&g.name&&(k[v]=g.name);l.splice(r,0,a);p&&(this.data.splice(r,0,null),this.processData());"point"===f.legendType&&this.generatePoints();
d&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(g,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;c&&m.redraw(e)},removePoint:function(a,c,d){var f=this,e=f.data,h=e[a],m=f.points,k=f.chart,l=function(){m&&m.length===e.length&&m.splice(a,1);e.splice(a,1);f.options.data.splice(a,1);f.updateParallelArrays(h||{series:f},"splice",a,1);h&&h.destroy();f.isDirty=!0;f.isDirtyData=!0;c&&k.redraw()};A(d,k);c=b(c,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,
c,d){function f(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();b(a,!0)&&h.redraw(c)}var e=this,h=e.chart;!1!==d?k(e,"remove",null,f):f()},update:function(a,c){var d=this,f=this.chart,e=this.userOptions,h=this.oldType||this.type,m=a.type||e.type||f.options.chart.type,k=r[h].prototype,p=["group","markerGroup","dataLabelsGroup"],g;if(m&&m!==h||void 0!==a.zIndex)p.length=0;n(p,function(a){p[a]=d[a];delete d[a]});a=H(e,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},
a);this.remove(!1,null,!1);for(g in k)this[g]=void 0;l(this,r[m||h].prototype);n(p,function(a){d[a]=p[a]});this.init(f,a);this.oldType=h;f.linkSeries();b(c,!0)&&f.redraw(!1)}});l(C.prototype,{update:function(a,c){var d=this.chart;a=d.options[this.coll][this.options.index]=H(this.userOptions,a);this.destroy(!0);this.init(d,l(a,{events:void 0}));d.isDirtyBox=!0;b(c,!0)&&d.redraw()},remove:function(a){for(var c=this.chart,d=this.coll,f=this.series,e=f.length;e--;)f[e]&&f[e].remove(!1);t(c.axes,this);
t(c[d],this);c.options[d].splice(this.options.index,1);n(c[d],function(a,b){a.options.index=b});this.destroy();c.isDirtyBox=!0;b(a,!0)&&c.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(I);(function(a){var B=a.color,z=a.each,C=a.map,E=a.pick,u=a.Series,h=a.seriesType;h("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(){var a=[],h=[],l=this.xAxis,k=this.yAxis,e=k.stacks[this.stackKey],c={},
p=this.points,u=this.index,b=k.series,m=b.length,d,r=E(k.options.reversedStacks,!0)?1:-1,A,v;if(this.options.stacking){for(A=0;A<p.length;A++)c[p[A].x]=p[A];for(v in e)null!==e[v].total&&h.push(v);h.sort(function(a,b){return a-b});d=C(b,function(){return this.visible});z(h,function(b,p){var f=0,n,q;if(c[b]&&!c[b].isNull)a.push(c[b]),z([-1,1],function(a){var f=1===a?"rightNull":"leftNull",k=0,l=e[h[p+a]];if(l)for(A=u;0<=A&&A<m;)n=l.points[A],n||(A===u?c[b][f]=!0:d[A]&&(q=e[b].points[A])&&(k-=q[1]-
q[0])),A+=r;c[b][1===a?"rightCliff":"leftCliff"]=k});else{for(A=u;0<=A&&A<m;){if(n=e[b].points[A]){f=n[1];break}A+=r}f=k.translate(f,0,1,0,1);a.push({isNull:!0,plotX:l.translate(b,0,0,0,1),x:b,plotY:f,yBottom:f})}})}return a},getGraphPath:function(a){var h=u.prototype.getGraphPath,l=this.options,k=l.stacking,e=this.yAxis,c,p,n=[],b=[],m=this.index,d,r=e.stacks[this.stackKey],A=l.threshold,v=e.getThreshold(l.threshold),f,l=l.connectNulls||"percent"===k,y=function(c,f,h){var l=a[c];c=k&&r[l.x].points[m];
var p=l[h+"Null"]||0;h=l[h+"Cliff"]||0;var q,t,l=!0;h||p?(q=(p?c[0]:c[1])+h,t=c[0]+h,l=!!p):!k&&a[f]&&a[f].isNull&&(q=t=A);void 0!==q&&(b.push({plotX:d,plotY:null===q?v:e.getThreshold(q),isNull:l,isCliff:!0}),n.push({plotX:d,plotY:null===t?v:e.getThreshold(t),doCurve:!1}))};a=a||this.points;k&&(a=this.getStackPoints());for(c=0;c<a.length;c++)if(p=a[c].isNull,d=E(a[c].rectPlotX,a[c].plotX),f=E(a[c].yBottom,v),!p||l)l||y(c,c-1,"left"),p&&!k&&l||(b.push(a[c]),n.push({x:c,plotX:d,plotY:f})),l||y(c,c+
1,"right");c=h.call(this,b,!0,!0);n.reversed=!0;p=h.call(this,n,!0,!0);p.length&&(p[0]="L");p=c.concat(p);h=h.call(this,b,!1,l);p.xMap=c.xMap;this.areaPath=p;return h},drawGraph:function(){this.areaPath=[];u.prototype.drawGraph.apply(this);var a=this,h=this.areaPath,l=this.options,k=[["area","highcharts-area",this.color,l.fillColor]];z(this.zones,function(e,c){k.push(["zone-area-"+c,"highcharts-area highcharts-zone-area-"+c+" "+e.className,e.color||a.color,e.fillColor||l.fillColor])});z(k,function(e){var c=
e[0],k=a[c];k?(k.endX=h.xMap,k.animate({d:h})):(k=a[c]=a.chart.renderer.path(h).addClass(e[1]).attr({fill:E(e[3],B(e[2]).setOpacity(E(l.fillOpacity,.75)).get()),zIndex:0}).add(a.group),k.isArea=!0);k.startX=h.xMap;k.shiftUnit=l.step?2:1})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle})})(I);(function(a){var B=a.pick;a=a.seriesType;a("spline","line",{},{getPointSpline:function(a,C,E){var u=C.plotX,h=C.plotY,n=a[E-1];E=a[E+1];var t,l,k,e;if(n&&!n.isNull&&!1!==n.doCurve&&!C.isCliff&&E&&!E.isNull&&
!1!==E.doCurve&&!C.isCliff){a=n.plotY;k=E.plotX;E=E.plotY;var c=0;t=(1.5*u+n.plotX)/2.5;l=(1.5*h+a)/2.5;k=(1.5*u+k)/2.5;e=(1.5*h+E)/2.5;k!==t&&(c=(e-l)*(k-u)/(k-t)+h-e);l+=c;e+=c;l>a&&l>h?(l=Math.max(a,h),e=2*h-l):l<a&&l<h&&(l=Math.min(a,h),e=2*h-l);e>E&&e>h?(e=Math.max(E,h),l=2*h-e):e<E&&e<h&&(e=Math.min(E,h),l=2*h-e);C.rightContX=k;C.rightContY=e}C=["C",B(n.rightContX,n.plotX),B(n.rightContY,n.plotY),B(t,u),B(l,h),u,h];n.rightContX=n.rightContY=null;return C}})})(I);(function(a){var B=a.seriesTypes.area.prototype,
z=a.seriesType;z("areaspline","spline",a.defaultPlotOptions.area,{getStackPoints:B.getStackPoints,getGraphPath:B.getGraphPath,setStackCliffs:B.setStackCliffs,drawGraph:B.drawGraph,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle})})(I);(function(a){var B=a.animObject,z=a.color,C=a.each,E=a.extend,u=a.isNumber,h=a.merge,n=a.pick,t=a.Series,l=a.seriesType,k=a.svg;l("column","line",{borderRadius:0,groupPadding:.2,marker:null,pointPadding:.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{halo:!1,
brightness:.1,shadow:!1},select:{color:"#cccccc",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},softThreshold:!1,startFromThreshold:!0,stickyTracking:!1,tooltip:{distance:6},threshold:0,borderColor:"#ffffff"},{cropShoulder:0,directTouch:!0,trackerGroups:["group","dataLabelsGroup"],negStacks:!0,init:function(){t.prototype.init.apply(this,arguments);var a=this,c=a.chart;c.hasRendered&&C(c.series,function(c){c.type===a.type&&(c.isDirty=!0)})},getColumnMetrics:function(){var a=
this,c=a.options,h=a.xAxis,k=a.yAxis,b=h.reversed,m,d={},l=0;!1===c.grouping?l=1:C(a.chart.series,function(b){var c=b.options,f=b.yAxis,e;b.type===a.type&&b.visible&&k.len===f.len&&k.pos===f.pos&&(c.stacking?(m=b.stackKey,void 0===d[m]&&(d[m]=l++),e=d[m]):!1!==c.grouping&&(e=l++),b.columnIndex=e)});var t=Math.min(Math.abs(h.transA)*(h.ordinalSlope||c.pointRange||h.closestPointRange||h.tickInterval||1),h.len),v=t*c.groupPadding,f=(t-2*v)/(l||1),c=Math.min(c.maxPointWidth||h.len,n(c.pointWidth,f*(1-
2*c.pointPadding)));a.columnMetrics={width:c,offset:(f-c)/2+(v+((a.columnIndex||0)+(b?1:0))*f-t/2)*(b?-1:1)};return a.columnMetrics},crispCol:function(a,c,h,k){var b=this.chart,e=this.borderWidth,d=-(e%2?.5:0),e=e%2?.5:1;b.inverted&&b.renderer.isVML&&(e+=1);h=Math.round(a+h)+d;a=Math.round(a)+d;k=Math.round(c+k)+e;d=.5>=Math.abs(c)&&.5<k;c=Math.round(c)+e;k-=c;d&&k&&(--c,k+=1);return{x:a,y:c,width:h-a,height:k}},translate:function(){var a=this,c=a.chart,h=a.options,k=a.dense=2>a.closestPointRange*
a.xAxis.transA,k=a.borderWidth=n(h.borderWidth,k?0:1),b=a.yAxis,m=a.translatedThreshold=b.getThreshold(h.threshold),d=n(h.minPointLength,5),l=a.getColumnMetrics(),u=l.width,v=a.barW=Math.max(u,1+2*k),f=a.pointXOffset=l.offset;c.inverted&&(m-=.5);h.pointPadding&&(v=Math.ceil(v));t.prototype.translate.apply(a);C(a.points,function(e){var h=n(e.yBottom,m),k=999+Math.abs(h),k=Math.min(Math.max(-k,e.plotY),b.len+k),l=e.plotX+f,p=v,r=Math.min(k,h),t,y=Math.max(k,h)-r;Math.abs(y)<d&&d&&(y=d,t=!b.reversed&&
!e.negative||b.reversed&&e.negative,r=Math.abs(r-m)>d?h-d:m-(t?d:0));e.barX=l;e.pointWidth=u;e.tooltipPos=c.inverted?[b.len+b.pos-c.plotLeft-k,a.xAxis.len-l-p/2,y]:[l+p/2,k+b.pos-c.plotTop,y];e.shapeType="rect";e.shapeArgs=a.crispCol.apply(a,e.isNull?[e.plotX,b.len/2,0,0]:[l,r,p,y])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")},pointAttribs:function(a,c){var e=this.options,k,b=this.pointAttrToOptions||
{};k=b.stroke||"borderColor";var m=b["stroke-width"]||"borderWidth",d=a&&a.color||this.color,l=a[k]||e[k]||this.color||d,n=a[m]||e[m]||this[m]||0,b=e.dashStyle;a&&this.zones.length&&(d=(d=a.getZone())&&d.color||a.options.color||this.color);c&&(a=h(e.states[c],a.options.states&&a.options.states[c]||{}),c=a.brightness,d=a.color||void 0!==c&&z(d).brighten(a.brightness).get()||d,l=a[k]||l,n=a[m]||n,b=a.dashStyle||b);k={fill:d,stroke:l,"stroke-width":n};e.borderRadius&&(k.r=e.borderRadius);b&&(k.dashstyle=
b);return k},drawPoints:function(){var a=this,c=this.chart,k=a.options,l=c.renderer,b=k.animationLimit||250,m;C(a.points,function(d){var e=d.graphic;if(u(d.plotY)&&null!==d.y){m=d.shapeArgs;if(e)e[c.pointCount<b?"animate":"attr"](h(m));else d.graphic=e=l[d.shapeType](m).add(d.group||a.group);e.attr(a.pointAttribs(d,d.selected&&"select")).shadow(k.shadow,null,k.stacking&&!k.borderRadius);e.addClass(d.getClassName(),!0)}else e&&(d.graphic=e.destroy())})},animate:function(a){var c=this,e=this.yAxis,
h=c.options,b=this.chart.inverted,m={};k&&(a?(m.scaleY=.001,a=Math.min(e.pos+e.len,Math.max(e.pos,e.toPixels(h.threshold))),b?m.translateX=a-e.len:m.translateY=a,c.group.attr(m)):(m[b?"translateX":"translateY"]=e.pos,c.group.animate(m,E(B(c.options.animation),{step:function(a,b){c.group.attr({scaleY:Math.max(.001,b.pos)})}})),c.animate=null))},remove:function(){var a=this,c=a.chart;c.hasRendered&&C(c.series,function(c){c.type===a.type&&(c.isDirty=!0)});t.prototype.remove.apply(a,arguments)}})})(I);
(function(a){a=a.seriesType;a("bar","column",null,{inverted:!0})})(I);(function(a){var B=a.Series;a=a.seriesType;a("scatter","line",{lineWidth:0,marker:{enabled:!0},tooltip:{headerFormat:'\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cspan style\x3d"font-size: 0.85em"\x3e {series.name}\x3c/span\x3e\x3cbr/\x3e',pointFormat:"x: \x3cb\x3e{point.x}\x3c/b\x3e\x3cbr/\x3ey: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e"}},{sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group",
"markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,kdDimensions:2,drawGraph:function(){this.options.lineWidth&&B.prototype.drawGraph.call(this)}})})(I);(function(a){var B=a.pick,z=a.relativeLength;a.CenteredSeriesMixin={getCenter:function(){var a=this.options,E=this.chart,u=2*(a.slicedOffset||0),h=E.plotWidth-2*u,E=E.plotHeight-2*u,n=a.center,n=[B(n[0],"50%"),B(n[1],"50%"),a.size||"100%",a.innerSize||0],t=Math.min(h,E),l,k;for(l=0;4>l;++l)k=n[l],a=2>l||2===l&&/%$/.test(k),n[l]=z(k,[h,E,t,n[2]][l])+
(a?u:0);n[3]>n[2]&&(n[3]=n[2]);return n}}})(I);(function(a){var B=a.addEvent,z=a.defined,C=a.each,E=a.extend,u=a.inArray,h=a.noop,n=a.pick,t=a.Point,l=a.Series,k=a.seriesType,e=a.setAnimation;k("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return null===this.y?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",
borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c=this,e=c.points,b=c.startAngleRad;a||(C(e,function(a){var d=a.graphic,e=a.shapeArgs;d&&(d.attr({r:a.startR||c.center[3]/2,start:b,end:b}),d.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,
e=0,h=this.points,b=h.length,k,d=this.options.ignoreHiddenPoint;for(a=0;a<b;a++)k=h[a],0>k.y&&(k.y=null),e+=d&&!k.visible?0:k.y;this.total=e;for(a=0;a<b;a++)k=h[a],k.percentage=0<e&&(k.visible||!d)?k.y/e*100:0,k.total=e},generatePoints:function(){l.prototype.generatePoints.call(this);this.updateTotals()},translate:function(a){this.generatePoints();var c=0,e=this.options,b=e.slicedOffset,h=b+(e.borderWidth||0),d,k,l,v=e.startAngle||0,f=this.startAngleRad=Math.PI/180*(v-90),v=(this.endAngleRad=Math.PI/
180*(n(e.endAngle,v+360)-90))-f,t=this.points,u=e.dataLabels.distance,e=e.ignoreHiddenPoint,F,q=t.length,x;a||(this.center=a=this.getCenter());this.getX=function(b,c){l=Math.asin(Math.min((b-a[1])/(a[2]/2+u),1));return a[0]+(c?-1:1)*Math.cos(l)*(a[2]/2+u)};for(F=0;F<q;F++){x=t[F];d=f+c*v;if(!e||x.visible)c+=x.percentage/100;k=f+c*v;x.shapeType="arc";x.shapeArgs={x:a[0],y:a[1],r:a[2]/2,innerR:a[3]/2,start:Math.round(1E3*d)/1E3,end:Math.round(1E3*k)/1E3};l=(k+d)/2;l>1.5*Math.PI?l-=2*Math.PI:l<-Math.PI/
2&&(l+=2*Math.PI);x.slicedTranslation={translateX:Math.round(Math.cos(l)*b),translateY:Math.round(Math.sin(l)*b)};d=Math.cos(l)*a[2]/2;k=Math.sin(l)*a[2]/2;x.tooltipPos=[a[0]+.7*d,a[1]+.7*k];x.half=l<-Math.PI/2||l>Math.PI/2?1:0;x.angle=l;h=Math.min(h,u/5);x.labelPos=[a[0]+d+Math.cos(l)*u,a[1]+k+Math.sin(l)*u,a[0]+d+Math.cos(l)*h,a[1]+k+Math.sin(l)*h,a[0]+d,a[1]+k,0>u?"center":x.half?"right":"left",l]}},drawGraph:null,drawPoints:function(){var a=this,e=a.chart.renderer,h,b,k,d,l=a.options.shadow;l&&
!a.shadowGroup&&(a.shadowGroup=e.g("shadow").add(a.group));C(a.points,function(c){if(null!==c.y){b=c.graphic;d=c.shapeArgs;h=c.getTranslate();var m=c.shadowGroup;l&&!m&&(m=c.shadowGroup=e.g("shadow").add(a.shadowGroup));m&&m.attr(h);k=a.pointAttribs(c,c.selected&&"select");b?b.setRadialReference(a.center).attr(k).animate(E(d,h)):(c.graphic=b=e[c.shapeType](d).setRadialReference(a.center).attr(h).add(a.group),c.visible||b.attr({visibility:"hidden"}),b.attr(k).attr({"stroke-linejoin":"round"}).shadow(l,
m));b.addClass(c.getClassName())}})},searchPoint:h,sortByAngle:function(a,e){a.sort(function(a,b){return void 0!==a.angle&&(b.angle-a.angle)*e})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:a.CenteredSeriesMixin.getCenter,getSymbol:h},{init:function(){t.prototype.init.apply(this,arguments);var a=this,e;a.name=n(a.name,"Slice");e=function(c){a.slice("select"===c.type)};B(a,"select",e);B(a,"unselect",e);return a},setVisible:function(a,e){var c=this,b=c.series,h=b.chart,d=b.options.ignoreHiddenPoint;
e=n(e,d);a!==c.visible&&(c.visible=c.options.visible=a=void 0===a?!c.visible:a,b.options.data[u(c,b.data)]=c.options,C(["graphic","dataLabel","connector","shadowGroup"],function(b){if(c[b])c[b][a?"show":"hide"](!0)}),c.legendItem&&h.legend.colorizeItem(c,a),a||"hover"!==c.state||c.setState(""),d&&(b.isDirty=!0),e&&h.redraw())},slice:function(a,h,k){var b=this.series;e(k,b.chart);n(h,!0);this.sliced=this.options.sliced=z(a)?a:!this.sliced;b.options.data[u(this,b.data)]=this.options;this.graphic.animate(this.getTranslate());
this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r,start:c.start,end:c.end})}})})(I);(function(a){var B=a.addEvent,z=a.arrayMax,C=a.defined,E=a.each,u=a.extend,h=a.format,n=a.map,t=a.merge,l=a.noop,k=a.pick,e=a.relativeLength,c=a.Series,
p=a.seriesTypes,H=a.stableSort;a.distribute=function(a,c){function b(a,b){return a.target-b.target}var e,h=!0,k=a,f=[],l;l=0;for(e=a.length;e--;)l+=a[e].size;if(l>c){H(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(l=e=0;l<=c;)l+=a[e].size,e++;f=a.splice(e-1,a.length)}H(a,b);for(a=n(a,function(a){return{size:a.size,targets:[a.target]}});h;){for(e=a.length;e--;)h=a[e],l=(Math.min.apply(0,h.targets)+Math.max.apply(0,h.targets))/2,h.pos=Math.min(Math.max(0,l-h.size/2),c-h.size);e=a.length;for(h=
!1;e--;)0<e&&a[e-1].pos+a[e-1].size>a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].pos+a[e-1].size>c&&(a[e-1].pos=c-a[e-1].size),a.splice(e,1),h=!0)}e=0;E(a,function(a){var b=0;E(a.targets,function(){k[e].pos=a.pos+b;b+=k[e].size;e++})});k.push.apply(k,f);H(k,b)};c.prototype.drawDataLabels=function(){var a=this,c=a.options,d=c.dataLabels,e=a.points,l,n,f=a.hasRendered||0,p,u,F=k(d.defer,!0),q=a.chart.renderer;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&&
a.dlProcessOptions(d),u=a.plotGroup("dataLabelsGroup","data-labels",F&&!f?"hidden":"visible",d.zIndex||6),F&&(u.attr({opacity:+f}),f||B(a,"afterAnimate",function(){a.visible&&u.show(!0);u[c.animation?"animate":"attr"]({opacity:1},{duration:200})})),n=d,E(e,function(b){var f,e=b.dataLabel,m,g,r,v=b.connector,y=!e,x;l=b.dlOptions||b.options&&b.options.dataLabels;if(f=k(l&&l.enabled,n.enabled)&&null!==b.y)for(g in d=t(n,l),m=b.getLabelConfig(),p=d.format?h(d.format,m):d.formatter.call(m,d),x=d.style,
r=d.rotation,x.color=k(d.color,x.color,a.color,"#000000"),"contrast"===x.color&&(x.color=d.inside||0>d.distance||c.stacking?q.getContrast(b.color||a.color):"#000000"),c.cursor&&(x.cursor=c.cursor),m={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:r,padding:d.padding,zIndex:1},m)void 0===m[g]&&delete m[g];!e||f&&C(p)?f&&C(p)&&(e?m.text=p:(e=b.dataLabel=q[r?"text":"label"](p,0,-9999,d.shape,null,null,d.useHTML,null,"data-label"),e.addClass("highcharts-data-label-color-"+
b.colorIndex+" "+(d.className||"")+(d.useHTML?"highcharts-tracker":""))),e.attr(m),e.css(x).shadow(d.shadow),e.added||e.add(u),a.alignDataLabel(b,e,d,null,y)):(b.dataLabel=e.destroy(),v&&(b.connector=v.destroy()))})};c.prototype.alignDataLabel=function(a,c,d,e,h){var b=this.chart,f=b.inverted,l=k(a.plotX,-9999),m=k(a.plotY,-9999),n=c.getBBox(),q,p=d.rotation,r=d.align,t=this.visible&&(a.series.forceDL||b.isInsidePlot(l,Math.round(m),f)||e&&b.isInsidePlot(l,f?e.x+1:e.y+e.height-1,f)),A="justify"===
k(d.overflow,"justify");t&&(q=d.style.fontSize,q=b.renderer.fontMetrics(q,c).b,e=u({x:f?b.plotWidth-m:l,y:Math.round(f?b.plotHeight-l:m),width:0,height:0},e),u(d,{width:n.width,height:n.height}),p?(A=!1,f=b.renderer.rotCorr(q,p),f={x:e.x+d.x+e.width/2+f.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},c[h?"attr":"animate"](f).attr({align:r}),l=(p+720)%360,l=180<l&&360>l,"left"===r?f.y-=l?n.height:0:"center"===r?(f.x-=n.width/2,f.y-=n.height/2):"right"===r&&(f.x-=n.width,f.y-=l?0:
n.height)):(c.align(d,null,e),f=c.alignAttr),A?this.justifyDataLabel(c,d,f,n,e,h):k(d.crop,!0)&&(t=b.isInsidePlot(f.x,f.y)&&b.isInsidePlot(f.x+n.width,f.y+n.height)),d.shape&&!p&&c.attr({anchorX:a.plotX,anchorY:a.plotY}));t||(c.attr({y:-9999}),c.placed=!1)};c.prototype.justifyDataLabel=function(a,c,d,e,h,k){var b=this.chart,l=c.align,m=c.verticalAlign,n,q,p=a.box?0:a.padding||0;n=d.x+p;0>n&&("right"===l?c.align="left":c.x=-n,q=!0);n=d.x+e.width-p;n>b.plotWidth&&("left"===l?c.align="right":c.x=b.plotWidth-
n,q=!0);n=d.y+p;0>n&&("bottom"===m?c.verticalAlign="top":c.y=-n,q=!0);n=d.y+e.height-p;n>b.plotHeight&&("top"===m?c.verticalAlign="bottom":c.y=b.plotHeight-n,q=!0);q&&(a.placed=!k,a.align(c,null,h))};p.pie&&(p.pie.prototype.drawDataLabels=function(){var b=this,e=b.data,d,h=b.chart,l=b.options.dataLabels,p=k(l.connectorPadding,10),f=k(l.connectorWidth,1),t=h.plotWidth,u=h.plotHeight,F,q=l.distance,x=b.center,B=x[2]/2,C=x[1],H=0<q,g,D,I,M,R=[[],[]],N,w,O,Q,P=[0,0,0,0];b.visible&&(l.enabled||b._hasPointLabels)&&
(E(e,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),c.prototype.drawDataLabels.apply(b),E(e,function(a){a.dataLabel&&a.visible&&(R[a.half].push(a),a.dataLabel._pos=null)}),E(R,function(c,f){var e,k,m=c.length,r,v,y;if(m)for(b.sortByAngle(c,f-.5),0<q&&(e=Math.max(0,C-B-q),k=Math.min(C+B+q,h.plotHeight),r=n(c,function(a){if(a.dataLabel)return y=a.dataLabel.getBBox().height||21,{target:a.labelPos[1]-
e+y/2,size:y,rank:a.y}}),a.distribute(r,k+y-e)),Q=0;Q<m;Q++)d=c[Q],I=d.labelPos,g=d.dataLabel,O=!1===d.visible?"hidden":"inherit",v=I[1],r?void 0===r[Q].pos?O="hidden":(M=r[Q].size,w=e+r[Q].pos):w=v,N=l.justify?x[0]+(f?-1:1)*(B+q):b.getX(w<e+2||w>k-2?v:w,f),g._attr={visibility:O,align:I[6]},g._pos={x:N+l.x+({left:p,right:-p}[I[6]]||0),y:w+l.y-10},I.x=N,I.y=w,null===b.options.size&&(D=g.getBBox().width,v=null,N-D<p?(v=Math.round(D-N+p),P[3]=Math.max(v,P[3])):N+D>t-p&&(v=Math.round(N+D-t+p),P[1]=Math.max(v,
P[1])),0>w-M/2?P[0]=Math.max(Math.round(-w+M/2),P[0]):w+M/2>u&&(P[2]=Math.max(Math.round(w+M/2-u),P[2])),g.sideOverflow=v)}),0===z(P)||this.verifyDataLabelOverflow(P))&&(this.placeDataLabels(),H&&f&&E(this.points,function(a){var c;F=a.connector;if((g=a.dataLabel)&&g._pos&&a.visible){O=g._attr.visibility;if(c=!F)a.connector=F=h.renderer.path().addClass("highcharts-data-label-connector highcharts-color-"+a.colorIndex).add(b.dataLabelsGroup),F.attr({"stroke-width":f,stroke:l.connectorColor||a.color||
"#666666"});F[c?"attr":"animate"]({d:b.connectorPath(a.labelPos)});F.attr("visibility",O)}else F&&(a.connector=F.destroy())}))},p.pie.prototype.connectorPath=function(a){var b=a.x,c=a.y;return k(this.options.dataLabels.softConnector,!0)?["M",b+("left"===a[6]?5:-5),c,"C",b,c,2*a[2]-a[4],2*a[3]-a[5],a[2],a[3],"L",a[4],a[5]]:["M",b+("left"===a[6]?5:-5),c,"L",a[2],a[3],"L",a[4],a[5]]},p.pie.prototype.placeDataLabels=function(){E(this.points,function(a){var b=a.dataLabel;b&&a.visible&&((a=b._pos)?(b.sideOverflow&&
(b._attr.width=b.getBBox().width-b.sideOverflow,b.css({width:b._attr.width+"px",textOverflow:"ellipsis"}),b.shortened=!0),b.attr(b._attr),b[b.moved?"animate":"attr"](a),b.moved=!0):b&&b.attr({y:-9999}))},this)},p.pie.prototype.alignDataLabel=l,p.pie.prototype.verifyDataLabelOverflow=function(a){var b=this.center,c=this.options,h=c.center,k=c.minSize||80,l,f;null!==h[0]?l=Math.max(b[2]-Math.max(a[1],a[3]),k):(l=Math.max(b[2]-a[1]-a[3],k),b[0]+=(a[3]-a[1])/2);null!==h[1]?l=Math.max(Math.min(l,b[2]-
Math.max(a[0],a[2])),k):(l=Math.max(Math.min(l,b[2]-a[0]-a[2]),k),b[1]+=(a[0]-a[2])/2);l<b[2]?(b[2]=l,b[3]=Math.min(e(c.innerSize||0,l),l),this.translate(b),this.drawDataLabels&&this.drawDataLabels()):f=!0;return f});p.column&&(p.column.prototype.alignDataLabel=function(a,e,d,h,l){var b=this.chart.inverted,f=a.series,m=a.dlBox||a.shapeArgs,n=k(a.below,a.plotY>k(this.translatedThreshold,f.yAxis.len)),p=k(d.inside,!!this.options.stacking);m&&(h=t(m),0>h.y&&(h.height+=h.y,h.y=0),m=h.y+h.height-f.yAxis.len,
0<m&&(h.height-=m),b&&(h={x:f.yAxis.len-h.y-h.height,y:f.xAxis.len-h.x-h.width,width:h.height,height:h.width}),p||(b?(h.x+=n?0:h.width,h.width=0):(h.y+=n?h.height:0,h.height=0)));d.align=k(d.align,!b||p?"center":n?"right":"left");d.verticalAlign=k(d.verticalAlign,b||p?"middle":n?"top":"bottom");c.prototype.alignDataLabel.call(this,a,e,d,h,l)})})(I);(function(a){var B=a.Chart,z=a.each,C=a.pick,E=a.addEvent;B.prototype.callbacks.push(function(a){function h(){var h=[];z(a.series||[],function(a){var l=
a.options.dataLabels,k=a.dataLabelCollections||["dataLabel"];(l.enabled||a._hasPointLabels)&&!l.allowOverlap&&a.visible&&z(k,function(e){z(a.points,function(a){a[e]&&(a[e].labelrank=C(a.labelrank,a.shapeArgs&&a.shapeArgs.height),h.push(a[e]))})})});a.hideOverlappingLabels(h)}h();E(a,"redraw",h)});B.prototype.hideOverlappingLabels=function(a){var h=a.length,n,t,l,k,e,c,p,u,b,m=function(a,b,c,e,f,h,k,l){return!(f>a+c||f+k<a||h>b+e||h+l<b)};for(t=0;t<h;t++)if(n=a[t])n.oldOpacity=n.opacity,n.newOpacity=
1;a.sort(function(a,b){return(b.labelrank||0)-(a.labelrank||0)});for(t=0;t<h;t++)for(l=a[t],n=t+1;n<h;++n)if(k=a[n],l&&k&&l.placed&&k.placed&&0!==l.newOpacity&&0!==k.newOpacity&&(e=l.alignAttr,c=k.alignAttr,p=l.parentGroup,u=k.parentGroup,b=2*(l.box?0:l.padding),e=m(e.x+p.translateX,e.y+p.translateY,l.width-b,l.height-b,c.x+u.translateX,c.y+u.translateY,k.width-b,k.height-b)))(l.labelrank<k.labelrank?l:k).newOpacity=0;z(a,function(a){var b,c;a&&(c=a.newOpacity,a.oldOpacity!==c&&a.placed&&(c?a.show(!0):
b=function(){a.hide()},a.alignAttr.opacity=c,a[a.isOld?"animate":"attr"](a.alignAttr,null,b)),a.isOld=!0)})}})(I);(function(a){var B=a.addEvent,z=a.Chart,C=a.createElement,E=a.css,u=a.defaultOptions,h=a.defaultPlotOptions,n=a.each,t=a.extend,l=a.fireEvent,k=a.hasTouch,e=a.inArray,c=a.isObject,p=a.Legend,H=a.merge,b=a.pick,m=a.Point,d=a.Series,r=a.seriesTypes,A=a.svg;a=a.TrackerMixin={drawTrackerPoint:function(){var a=this,b=a.chart.pointer,c=function(a){var c=b.getPointFromEvent(a);if(void 0!==c)c.onMouseOver(a)};
n(a.points,function(a){a.graphic&&(a.graphic.element.point=a);a.dataLabel&&(a.dataLabel.div?a.dataLabel.div.point=a:a.dataLabel.element.point=a)});a._hasTracking||(n(a.trackerGroups,function(d){if(a[d]){a[d].addClass("highcharts-tracker").on("mouseover",c).on("mouseout",function(a){b.onTrackerMouseOut(a)});if(k)a[d].on("touchstart",c);a.options.cursor&&a[d].css(E).css({cursor:a.options.cursor})}}),a._hasTracking=!0)},drawTrackerGraph:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?
a.areaPath:a.graphPath),e=d.length,h=a.chart,l=h.pointer,m=h.renderer,p=h.options.tooltip.snap,t=a.tracker,g,r=function(){if(h.hoverSeries!==a)a.onMouseOver()},u="rgba(192,192,192,"+(A?.0001:.002)+")";if(e&&!c)for(g=e+1;g--;)"M"===d[g]&&d.splice(g+1,0,d[g+1]-p,d[g+2],"L"),(g&&"M"===d[g]||g===e)&&d.splice(g,0,"L",d[g-2]+p,d[g-1]);t?t.attr({d:d}):a.graph&&(a.tracker=m.path(d).attr({"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:u,fill:c?u:"none","stroke-width":a.graph.strokeWidth()+
(c?0:2*p),zIndex:2}).add(a.group),n([a.tracker,a.markerGroup],function(a){a.addClass("highcharts-tracker").on("mouseover",r).on("mouseout",function(a){l.onTrackerMouseOut(a)});b.cursor&&a.css({cursor:b.cursor});if(k)a.on("touchstart",r)}))}};r.column&&(r.column.prototype.drawTracker=a.drawTrackerPoint);r.pie&&(r.pie.prototype.drawTracker=a.drawTrackerPoint);r.scatter&&(r.scatter.prototype.drawTracker=a.drawTrackerPoint);t(p.prototype,{setItemEvents:function(a,b,c){var d=this,e=d.chart.renderer.boxWrapper,
f="highcharts-legend-"+(a.series?"point":"series")+"-active";(c?b:a.legendGroup).on("mouseover",function(){a.setState("hover");e.addClass(f);b.css(d.options.itemHoverStyle)}).on("mouseout",function(){b.css(a.visible?d.itemStyle:d.itemHiddenStyle);e.removeClass(f);a.setState()}).on("click",function(b){var c=function(){a.setVisible&&a.setVisible()};b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):l(a,"legendItemClick",b,c)})},createCheckboxForItem:function(a){a.checkbox=C("input",
{type:"checkbox",checked:a.selected,defaultChecked:a.selected},this.options.itemCheckboxStyle,this.chart.container);B(a.checkbox,"click",function(b){l(a.series||a,"checkboxClick",{checked:b.target.checked,item:a},function(){a.select()})})}});u.legend.itemStyle.cursor="pointer";t(z.prototype,{showResetZoom:function(){var a=this,b=u.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,h="chart"===c.relativeTo?null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},
d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).addClass("highcharts-reset-zoom").add().align(c.position,!1,h)},zoomOut:function(){var a=this;l(a,"selection",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var d,e=this.pointer,h=!1,k;!a||a.resetSelection?n(this.axes,function(a){d=a.zoom()}):n(a.xAxis.concat(a.yAxis),function(a){var b=a.axis;e[b.isXAxis?"zoomX":"zoomY"]&&(d=b.zoom(a.min,a.max),b.displayBtn&&(h=!0))});k=this.resetZoomButton;h&&!k?this.showResetZoom():
!h&&c(k)&&(this.resetZoomButton=k.destroy());d&&this.redraw(b(this.options.chart.animation,a&&a.animation,100>this.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&n(d,function(a){a.setState()});n("xy"===b?[1,0]:[1],function(b){b=c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],k=(b.pointRange||0)/2,g=b.getExtremes(),l=b.toValue(h-f,!0)+k,k=b.toValue(h+b.len-f,!0)-k,m=k<l,h=m?k:l,l=m?l:k,m=b.toValue(b.toPixels(g.min)-b.minPixelPadding),
k=b.toValue(b.toPixels(g.max)+b.minPixelPadding),m=Math.min(g.dataMin,m)-h,g=l-Math.max(g.dataMax,k);b.series.length&&0>m&&0>g&&(b.setExtremes(h,l,!1,!1,{trigger:"pan"}),e=!0);c[d]=f});e&&c.redraw(!1);E(c.container,{cursor:"move"})}});t(m.prototype,{select:function(a,c){var d=this,f=d.series,h=f.chart;a=b(a,!d.selected);d.firePointEvent(a?"select":"unselect",{accumulate:c},function(){d.selected=d.options.selected=a;f.options.data[e(d,f.data)]=d.options;d.setState(a&&"select");c||n(h.getSelectedPoints(),
function(a){a.selected&&a!==d&&(a.selected=a.options.selected=!1,f.options.data[e(a,f.data)]=a.options,a.setState(""),a.firePointEvent("unselect"))})})},onMouseOver:function(a){var b=this.series.chart.pointer;this.firePointEvent("mouseOver");b.runPointActions(a,this)},onMouseOut:function(){var a=this.series.chart;this.firePointEvent("mouseOut");n(a.hoverPoints||[],function(a){a.setState()});a.hoverPoints=a.hoverPoint=null},importEvents:function(){if(!this.hasImportedEvents){var a=H(this.series.options.point,
this.options).events,b;this.events=a;for(b in a)B(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a,c){var d=Math.floor(this.plotX),e=this.plotY,f=this.series,k=f.options.states[a]||{},l=h[f.type].marker&&f.options.marker,m=l&&!1===l.enabled,n=l&&l.states&&l.states[a]||{},p=!1===n.enabled,g=f.stateMarkerGraphic,r=this.marker||{},u=f.chart,v=f.halo,z,A=l&&f.markerAttribs;a=a||"";if(!(a===this.state&&!c||this.selected&&"select"!==a||!1===k.enabled||a&&(p||m&&!1===n.enabled)||a&&r.states&&
r.states[a]&&!1===r.states[a].enabled)){A&&(z=f.markerAttribs(this,a));if(this.graphic)this.state&&this.graphic.removeClass("highcharts-point-"+this.state),a&&this.graphic.addClass("highcharts-point-"+a),this.graphic.attr(f.pointAttribs(this,a)),z&&this.graphic.animate(z,b(u.options.chart.animation,n.animation,l.animation)),g&&g.hide();else{if(a&&n){l=r.symbol||f.symbol;g&&g.currentSymbol!==l&&(g=g.destroy());if(g)g[c?"animate":"attr"]({x:z.x,y:z.y});else l&&(f.stateMarkerGraphic=g=u.renderer.symbol(l,
z.x,z.y,z.width,z.height).add(f.markerGroup),g.currentSymbol=l);g&&g.attr(f.pointAttribs(this,a))}g&&(g[a&&u.isInsidePlot(d,e,u.inverted)?"show":"hide"](),g.element.point=this)}(d=k.halo)&&d.size?(v||(f.halo=v=u.renderer.path().add(A?f.markerGroup:f.group)),v[c?"animate":"attr"]({d:this.haloPath(d.size)}),v.attr({"class":"highcharts-halo highcharts-color-"+b(this.colorIndex,f.colorIndex)}),v.point=this,v.attr(t({fill:this.color||f.color,"fill-opacity":d.opacity,zIndex:-1},d.attributes))):v&&v.point&&
v.point.haloPath&&v.animate({d:v.point.haloPath(0)});this.state=a}},haloPath:function(a){return this.series.chart.renderer.symbols.circle(Math.floor(this.plotX)-a,this.plotY-a,2*a,2*a)}});t(d.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&l(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;b.hoverSeries=null;if(d)d.onMouseOut();
this&&a.events.mouseOut&&l(this,"mouseOut");!c||a.stickyTracking||c.shared&&!this.noSharedTooltip||c.hide();this.setState()},setState:function(a){var c=this,d=c.options,e=c.graph,h=d.states,k=d.lineWidth,d=0;a=a||"";if(c.state!==a&&(n([c.group,c.markerGroup,c.dataLabelsGroup],function(b){b&&(c.state&&b.removeClass("highcharts-series-"+c.state),a&&b.addClass("highcharts-series-"+a))}),c.state=a,!h[a]||!1!==h[a].enabled)&&(a&&(k=h[a].lineWidth||k+(h[a].lineWidthPlus||0)),e&&!e.dashstyle))for(k={"stroke-width":k},
e.animate(k,b(c.chart.options.chart.animation,h[a]&&h[a].animation));c["zone-graph-"+d];)c["zone-graph-"+d].attr(k),d+=1},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,h=d.options.chart.ignoreHiddenSeries,k=c.visible;f=(c.visible=a=c.options.visible=c.userOptions.visible=void 0===a?!k:a)?"show":"hide";n(["group","dataLabelsGroup","markerGroup","tracker","tt"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c||(d.hoverPoint&&d.hoverPoint.series)===c)c.onMouseOut();e&&d.legend.colorizeItem(c,
a);c.isDirty=!0;c.options.stacking&&n(d.series,function(a){a.options.stacking&&a.visible&&(a.isDirty=!0)});n(c.linkedSeries,function(b){b.setVisible(a,!1)});h&&(d.isDirtyBox=!0);!1!==b&&d.redraw();l(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=void 0===a?!this.selected:a;this.checkbox&&(this.checkbox.checked=a);l(this,a?"select":"unselect")},drawTracker:a.drawTrackerGraph})})(I);(function(a){var B=a.Chart,z=a.each,C=a.inArray,E=
a.isArray,u=a.isObject,h=a.pick,n=a.splat;B.prototype.setResponsive=function(h){var l=this.options.responsive,k=[],e=this.currentResponsive;l&&l.rules&&z(l.rules,function(c){void 0===c._id&&(c._id=a.uniqueKey());this.matchResponsiveRule(c,k,h)},this);var c=a.merge.apply(0,a.map(k,function(c){return a.find(l.rules,function(a){return a._id===c}).chartOptions})),k=k.toString()||void 0;k!==(e&&e.ruleIds)&&(e&&this.update(e.undoOptions,h),k?(this.currentResponsive={ruleIds:k,mergedOptions:c,undoOptions:this.currentOptions(c)},
this.update(c,h)):this.currentResponsive=void 0)};B.prototype.matchResponsiveRule=function(a,l){var k=a.condition;(k.callback||function(){return this.chartWidth<=h(k.maxWidth,Number.MAX_VALUE)&&this.chartHeight<=h(k.maxHeight,Number.MAX_VALUE)&&this.chartWidth>=h(k.minWidth,0)&&this.chartHeight>=h(k.minHeight,0)}).call(this)&&l.push(a._id)};B.prototype.currentOptions=function(a){function h(a,c,k,l){var b,e;for(b in a)if(!l&&-1<C(b,["series","xAxis","yAxis"]))for(a[b]=n(a[b]),k[b]=[],e=0;e<a[b].length;e++)c[b][e]&&
(k[b][e]={},h(a[b][e],c[b][e],k[b][e],l+1));else u(a[b])?(k[b]=E(a[b])?[]:{},h(a[b],c[b]||{},k[b],l+1)):k[b]=c[b]||null}var k={};h(a,this.options,k,0);return k}})(I);return I});

View File

@ -0,0 +1,17 @@
/*
Highcharts JS v3.0.5 (2013-08-23)
Standalone Highcharts Framework
License: MIT License
*/
var HighchartsAdapter=function(){function n(c){function a(a,b,d){a.removeEventListener(b,d,!1)}function d(a,b,d){d=a.HCProxiedMethods[d.toString()];a.detachEvent("on"+b,d)}function b(b,c){var g=b.HCEvents,i,h,l,f;if(b.removeEventListener)i=a;else if(b.attachEvent)i=d;else return;c?(h={},h[c]=!0):h=g;for(f in h)if(g[f])for(l=g[f].length;l--;)i(b,f,g[f][l])}c.HCExtended||Highcharts.extend(c,{HCExtended:!0,HCEvents:{},bind:function(b,a){var d=this,c=this.HCEvents,h;if(d.addEventListener)d.addEventListener(b,
a,!1);else if(d.attachEvent){h=function(b){a.call(d,b)};if(!d.HCProxiedMethods)d.HCProxiedMethods={};d.HCProxiedMethods[a.toString()]=h;d.attachEvent("on"+b,h)}c[b]===q&&(c[b]=[]);c[b].push(a)},unbind:function(c,k){var g,i;c?(g=this.HCEvents[c]||[],k?(i=HighchartsAdapter.inArray(k,g),i>-1&&(g.splice(i,1),this.HCEvents[c]=g),this.removeEventListener?a(this,c,k):this.attachEvent&&d(this,c,k)):(b(this,c),this.HCEvents[c]=[])):(b(this),this.HCEvents={})},trigger:function(b,a){var d=this.HCEvents[b]||
[],c=d.length,h,f;for(h=function(){a.defaultPrevented=!0};c--;){f=d[c];if(a.stopped)break;a.preventDefault=h;a.target=this;f.call(this,a)===!1&&a.preventDefault()}}});return c}var q,f=document,o=[],j=[],p,m;Math.easeInOutSine=function(c,a,d,b){return-d/2*(Math.cos(Math.PI*c/b)-1)+a};return{init:function(c){if(!f.defaultView)this._getStyle=function(a,d){var b;return a.style[d]?a.style[d]:(d==="opacity"&&(d="filter"),b=a.currentStyle[d.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()})],d==="filter"&&
(b=b.replace(/alpha\(opacity=([0-9]+)\)/,function(b,a){return a/100})),b===""?1:b)},this.adapterRun=function(a,d){var b={width:"clientWidth",height:"clientHeight"}[d];if(b)return a.style.zoom=1,a[b]-2*parseInt(HighchartsAdapter._getStyle(a,"padding"),10)};if(!Array.prototype.forEach)this.each=function(a,d){for(var b=0,c=a.length;b<c;b++)if(d.call(a[b],a[b],b,a)===!1)return b};if(!Array.prototype.indexOf)this.inArray=function(a,d){var b,c=0;if(d)for(b=d.length;c<b;c++)if(d[c]===a)return c;return-1};
if(!Array.prototype.filter)this.grep=function(a,d){for(var b=[],c=0,f=a.length;c<f;c++)d(a[c],c)&&b.push(a[c]);return b};m=function(a,c,b){this.options=c;this.elem=a;this.prop=b};m.prototype={update:function(){var a;a=this.paths;var d=this.elem,b=d.element;a&&b?d.attr("d",c.step(a[0],a[1],this.now,this.toD)):d.attr?b&&d.attr(this.prop,this.now):(a={},a[d]=this.now+this.unit,Highcharts.css(d,a));this.options.step&&this.options.step.call(this.elem,this.now,this)},custom:function(a,c,b){var e=this,f=
function(a){return e.step(a)},g;this.startTime=+new Date;this.start=a;this.end=c;this.unit=b;this.now=this.start;this.pos=this.state=0;f.elem=this.elem;f()&&j.push(f)===1&&(p=setInterval(function(){for(g=0;g<j.length;g++)j[g]()||j.splice(g--,1);j.length||clearInterval(p)},13))},step:function(a){var c=+new Date,b;b=this.options;var e;if(this.elem.stopAnimation)b=!1;else if(a||c>=b.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();a=this.options.curAnim[this.prop]=!0;for(e in b.curAnim)b.curAnim[e]!==
!0&&(a=!1);a&&b.complete&&b.complete.call(this.elem);b=!1}else e=c-this.startTime,this.state=e/b.duration,this.pos=b.easing(e,0,1,b.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update(),b=!0;return b}};this.animate=function(a,d,b){var e,f="",g,i,h;a.stopAnimation=!1;if(typeof b!=="object"||b===null)e=arguments,b={duration:e[2],easing:e[3],complete:e[4]};if(typeof b.duration!=="number")b.duration=400;b.easing=Math[b.easing]||Math.easeInOutSine;b.curAnim=Highcharts.extend({},d);
for(h in d)i=new m(a,b,h),g=null,h==="d"?(i.paths=c.init(a,a.d,d.d),i.toD=d.d,e=0,g=1):a.attr?e=a.attr(h):(e=parseFloat(this._getStyle(a,h))||0,h!=="opacity"&&(f="px")),g||(g=parseFloat(d[h])),i.custom(e,g,f)}},_getStyle:function(c,a){return window.getComputedStyle(c).getPropertyValue(a)},getScript:function(c,a){var d=f.getElementsByTagName("head")[0],b=f.createElement("script");b.type="text/javascript";b.src=c;b.onload=a;d.appendChild(b)},inArray:function(c,a){return a.indexOf?a.indexOf(c):o.indexOf.call(a,
c)},adapterRun:function(c,a){return parseInt(HighchartsAdapter._getStyle(c,a),10)},grep:function(c,a){return o.filter.call(c,a)},map:function(c,a){for(var d=[],b=0,e=c.length;b<e;b++)d[b]=a.call(c[b],c[b],b,c);return d},offset:function(c){for(var a=0,d=0;c;)a+=c.offsetLeft,d+=c.offsetTop,c=c.offsetParent;return{left:a,top:d}},addEvent:function(c,a,d){n(c).bind(a,d)},removeEvent:function(c,a,d){n(c).unbind(a,d)},fireEvent:function(c,a,d,b){var e;f.createEvent&&(c.dispatchEvent||c.fireEvent)?(e=f.createEvent("Events"),
e.initEvent(a,!0,!0),e.target=c,Highcharts.extend(e,d),c.dispatchEvent?c.dispatchEvent(e):c.fireEvent(a,e)):c.HCExtended===!0&&(d=d||{},c.trigger(a,d));d&&d.defaultPrevented&&(b=null);b&&b(d)},washMouseEvent:function(c){return c},stop:function(c){c.stopAnimation=!0},each:function(c,a){return Array.prototype.forEach.call(c,a)}}}();

View File

@ -0,0 +1,299 @@
Highcharts.setOptions({
chart: {
style: {
fontFamily: 'Verdana'
}
},
global: {
useUTC: false
}
});
function changeServer(obj) {
if (obj.options[obj.selectedIndex].value != '') {
window.location = 'index.php?server='
+ obj.options[obj.selectedIndex].value;
} else {
window.location = 'index.php';
}
}
function changeCluster(obj) {
if (obj.options[obj.selectedIndex].value != '') {
window.location = 'stats.php?cluster='
+ obj.options[obj.selectedIndex].value;
} else {
window.location = 'stats.php';
}
}
function show(target)
{
var objects = document.getElementsByClassName(target);
for(i = 0 ; i < objects.length ; i++){
objects[i].style.display = '';
}
}
function hide(target)
{
var objects = document.getElementsByClassName(target);
for(i = 0 ; i < objects.length ; i++){
objects[i].style.display = 'none';
}
}
function changeCommand(obj) {
document.getElementById('request_key').value = '';
document.getElementById('request_duration').value = '';
document.getElementById('request_data').value = '';
document.getElementById('request_delay').value = '';
document.getElementById('request_value').value = '';
var command = obj.options[obj.selectedIndex].value;
var div_key = document.getElementById('div_key');
var div_duration = document.getElementById('div_duration');
var div_data = document.getElementById('div_data');
var div_delay = document.getElementById('div_delay');
var div_value = document.getElementById('div_value');
if (command == 'get' || command == 'delete') {
div_key.style.display = '';
div_duration.style.display = 'none';
div_data.style.display = 'none';
div_delay.style.display = 'none';
div_value.style.display = 'none';
} else if (command == 'set') {
div_key.style.display = '';
div_duration.style.display = '';
div_data.style.display = '';
div_delay.style.display = 'none';
div_value.style.display = 'none';
} else if (command == 'flush_all') {
div_key.style.display = 'none';
div_duration.style.display = 'none';
div_data.style.display = 'none';
div_delay.style.display = '';
div_value.style.display = 'none';
} else if (command == 'increment' || command == 'decrement') {
div_key.style.display = '';
div_duration.style.display = 'none';
div_data.style.display = 'none';
div_delay.style.display = 'none';
div_value.style.display = '';
} else {
div_key.style.display = 'none';
div_duration.style.display = 'none';
div_data.style.display = 'none';
div_delay.style.display = 'none';
div_value.style.display = 'none';
}
}
function executeHideShow(target, input, force) {
var object = document.getElementById(target);
var input = document.getElementById(input);
if ((object.style.display == "block") && (force != true)) {
input.value = "Show Console";
object.style.visibility = "hidden";
object.style.display = "none";
} else {
object.style.visibility = "visible";
object.style.display = "block";
input.value = "Hide Console";
}
}
function executeClear(target) {
var object = document.getElementById(target);
object.innerHTML = '';
}
function executeCommand(target, params) {
if (params != null) {
var request_url = 'commands.php?' + params;
execute(request_url, target, true);
return;
}
if (document.getElementById('request_command').value != '') {
var request_url = 'commands.php?request_command='
+ document.getElementById('request_command').value
+ '&request_key='
+ document.getElementById('request_key').value
+ '&request_duration='
+ document.getElementById('request_duration').value
+ '&request_data='
+ document.getElementById('request_data').value
+ '&request_delay='
+ document.getElementById('request_delay').value
+ '&request_value='
+ document.getElementById('request_value').value
+ '&request_server='
+ document.getElementById('request_server').value
+ '&request_api='
+ document.getElementById('request_api').value;
execute(request_url, target, true);
return;
}
}
function searchKey(target) {
if (document.getElementById('search_key').value != '') {
var request_url = 'commands.php?request_command=search'
+ '&request_key=' + document.getElementById('search_key').value
+ '&request_level=' + document.getElementById('search_level').value
+ '&request_more=' + document.getElementById('search_more').value
+ '&request_server='
+ document.getElementById('search_server').value;
execute(request_url, target, true);
}
}
function executeTelnet(target) {
if (document.getElementById('request_telnet').value != '') {
var request_url = 'commands.php?request_command=telnet'
+ '&request_telnet='
+ document.getElementById('request_telnet').value
+ '&request_server='
+ document.getElementById('request_telnet_server').value;
execute(request_url, target, true);
}
}
function execute(url, target, append) {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = function() {
onExecute(target, append);
};
req.open('GET', url, true);
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject('Microsoft.XMLHTTP');
if (req) {
req.onreadystatechange = function() {
onExecute(target, append);
};
req.open('GET', url, true);
req.send();
}
}
}
function onExecute(target, append) {
if (req.readyState == 1) {
document.getElementById('loading').style.visibility = "visible";
} else if (req.readyState == 4) {
document.getElementById('loading').style.visibility = "hidden";
if (req.status == 200 || req.status == 304) {
if (append == true) {
var object = document.getElementById(target);
object.innerHTML += req.responseText;
object.scrollTop = object.scrollHeight;
} else {
var object = document.getElementById(target);
object.innerHTML = req.responseText;
object.scrollTop = object.scrollHeight;
}
}
} else {
document.getElementById('loading').style.visibility = "hidden";
}
}
var server_id = 1;
var cluster_id = 1;
function addCluster() {
var clusterDiv = document.createElement('div');
cluster_id++;
clusterDiv.innerHTML = '<hr/><strong>Cluster <input type="text" style="width:200px;" name="cluster[' + cluster_id + ']" value=""/></strong>'
+ '<div style="margin-left:30px;margin-top:3px;">'
+ '<div style="width:150px;float:left;">Name (Optionnal)</div>'
+ '<div style="width:150px;float:left;margin-left:7px;">IP/Hostname</div>'
+ '<div style="width:50px;float:left;margin-left:7px;">Port</div></div>'
+ '<div style="margin-left:40px;margin-top:6px;" id="cluster_' + cluster_id + '_commands">'
+ '<a class="list button" href="javascript:addServer(' + cluster_id + ')">'
+ 'Add New Server to Cluster</a> <a class="list" style="padding:1px 2px;-moz-border-radius:3px;-webkit-border-radius:3px;" '
+ 'href="#" onclick="deleteServerOrCluster(\'cluster_' + cluster_id + '\')">Delete Cluster</a></div><br/>';
clusterDiv.setAttribute('id', 'cluster_' + cluster_id);
document.getElementById('server_form').appendChild(clusterDiv);
addServer(cluster_id);
}
function addServer(current_cluster_id) {
var serverDiv = document.createElement('div');
server_id++;
serverDiv.innerHTML = '<div style="margin-left:30px;margin-top:3px;">'
+ '<input type="text" style="width:150px;" name="server[' + current_cluster_id + '][' + server_id + '][name]"'
+ ' value="" id="name_' + server_id + '" onchange="nameOnChange(' + server_id + ') onKeyUp="hostOrPortOnChange(' + server_id + ')""/> '
+ '<input type="text" style="width:150px;" name="server[' + current_cluster_id + '][' + server_id + '][hostname]"'
+ ' value="hostname" id="host_' + server_id + '" onfocus="hostOnFocus(this)" onblur="hostOnBlur(this)" onchange="hostOrPortOnChange(' + server_id + ')"'
+ ' onchange="hostOrPortOnChange(' + server_id + ')" onKeyUp="hostOrPortOnChange(' + server_id + ')" /> '
+ '<input type="text" style="width:50px;" name="server[' + current_cluster_id + '][' + server_id + '][port]"'
+ ' value="port" id="port_' + server_id + '" onfocus="portOnFocus(this)" onblur="portOnBlur(this) onchange="hostOrPortOnChange(' + server_id + ')"/> '
+ '<a class="list button" style="padding:1px 2px;" href="#" onclick="deleteServerOrCluster(\'server_' + server_id + '\')">Delete</a>' + '</div>';
serverDiv.setAttribute('id', 'server_' + server_id);
document.getElementById('cluster_' + current_cluster_id).insertBefore(serverDiv, document.getElementById('cluster_' + current_cluster_id + '_commands'));
}
function deleteServerOrCluster(divID) {
var div = document.getElementById(divID);
div.parentNode.removeChild(div);
}
function nameOnChange(target) {
portObject = document.getElementById('port_' + target);
portObject.setAttribute("onchange", "return false;");
hostObject = document.getElementById('host_' + target);
hostObject.setAttribute("onchange", "return false;");
}
function hostOnFocus(object) {
if (object.value == 'hostname') {
object.value = '';
}
}
function hostOnBlur(object) {
if (object.value == '') {
object.value = 'hostname';
}
}
function hostOnChange(target) {
document.getElementById(target);
if (object.value == '') {
object.value = 'port';
}
}
function portOnFocus(object) {
if (object.value == 'port') {
object.value = '';
}
}
function portOnBlur(object) {
if (object.value == '') {
object.value = 'port';
}
}
function hostOrPortOnChange(target) {
nameObject = document.getElementById('name_' + target);
hostObject = document.getElementById('host_' + target);
portObject = document.getElementById('port_' + target);
if ((nameObject.value == '') || ((nameObject.value != hostObject.value + ':' + portObject.value))) {
nameObject.value = hostObject.value + ':' + portObject.value;
}
}
function ajax(url, target) {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = function() {
ajaxDone(target);
};
req.open("GET", url, true);
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject('Microsoft.XMLHTTP');
if (req) {
req.onreadystatechange = function() {
ajaxDone(target);
};
req.open("GET", url, true);
req.send();
}
}
setTimeout("ajax(page, 'stats')", timeout);
}
function ajaxDone(target) {
if (req.readyState == 4) {
if (req.status == 200 || req.status == 304) {
results = req.responseText;
document.getElementById(target).innerHTML = results;
} else {
document.getElementById(target).innerHTML = "Loading stats error : "
+ req.statusText;
}
}
}

View File

@ -0,0 +1,238 @@
body {
background-color: #FEFEFE;
font-family: Verdana,Tahoma,"Segoe UI", Arial;
font-size: 0.8em;
margin-top: 10px;
}
a {
color: #EEE;
text-decoration: none;
cursor: pointer;
}
a:hover {
color: #A00
}
input,select,textarea {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
border-width: 1px;
border-style: solid;
border-color: #AAA;
width: 298px;
font-family: Tahoma;
font-size: 1em;
}
textarea {
width: 494px;
resize: none;
}
select {
width: 300px;
}
input:focus,textarea:focus {
border-width: 1px;
border-style: solid;
border-color: #EEE;
}
input:hover {
color: #A00;
}
input[type=submit] {
cursor: pointer;
}
img {
border: none;
} /** hr */
hr {
height: 0;
border: none;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #EEE;
}
.menu {
border-width: 1px;
border-style: solid;
border-color: #a0312a;
color: #eee;
width: 198px;
}
.item {
font-family: "Bitstream Vera Sans Mono",
"Lucida Sans Typewriter",
"DejaVu Sans Mono",
Consolas,
"Andale Mono",
"Lucida Console",
"Liberation Mono",
"Nimbus Mono L",
Monaco,
"Courier New",
Courier,
monospace;
cursor: hand;
}
.loading {
text-decoration: blink;
visibility: hidden;
}
.full-size {
width: 980px;
}
.size-0 {
width: 494px;
}
.size-1 {
width: 696px;
}
.size-2 {
width: 398px;
}
.size-4 {
width: 290px;
}
.size-5 {
width: 226px;
}
.padding {
padding: 3px 7px 3px 7px;
}
.corner {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
.header {
border-width: 1px;
border-style: solid;
border-color: #9c3c36;
background: #B5463F;
font-weight: bold;
color: #fff;
clear: both
}
.sub-header {
border-width: 1px;
border-style: solid;
border-color: #514845;
background: #635855;
font-weight: bold;
color: #fff;
clear: both;
margin-top: 10px
}
.container {
border-width: 1px;
border-style: solid;
border-color: #d0d0d0;
background: #ebebeb;
font-weight: none;
color: #000;
margin-top: 1px;
clear: both
}
.list {
border-width: 1px;
border-style: solid;
border-color: #9c3c36;
background: #B5463F;
font-weight: bold;
color: #fff
}
.button {
padding: 1px 20px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px
}
.live {
font-family: "Bitstream Vera Sans Mono",
"Lucida Sans Typewriter",
"DejaVu Sans Mono",
Consolas,
"Andale Mono",
"Lucida Console",
"Liberation Mono",
"Nimbus Mono L",
Monaco,
"Courier New",
Courier,
monospace;
font-size: 12px;
overflow: visible;
white-space: pre-wrap
}
.line {
min-height: 18px;
padding-top: 3px;
padding-bottom: 2px;
clear: both
}
.left {
float: left;
min-width: 126px;
font-weight: bold
}
.right {
float: right
}
.setting {
min-width: 180px
}
.slabs {
min-width: 104px
}
.help {
cursor:help;
}
.container hr {
height: 0;
border: none;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #fff;
}
.grey {
color: #EEE
}
.green {
color: #40aaba
}
.red {
background: #b5463f;
color: #fff;
font-weight: bold
}

View File

@ -0,0 +1,197 @@
<div style="float:left;">
<div class="sub-header corner full-size padding">Console</div>
<div class="container corner full-size padding" id="console" style="visibility:visible;display:block;">
<pre id="container" style="font-size:11px;overflow:auto;min-height:180px;max-height:500px;" class="full-size live"></pre>
</div>
<div class="container corner full-size padding" style="text-align:right;">
<span style="float:left;">
<input class="header loading" type="submit" id="loading" value="Waiting for server response ..."/>
</span>
<input class="header" type="submit" onclick="javascript:executeClear('container')" value="Clear Console"/>
<input class="header" id="hide" type="submit" onclick="javascript:executeHideShow('console', 'hide');javascript:this.blur();" value="Hide Console">
</div>
<div class="sub-header corner full-size padding">Execute predefined <span class="green">Command</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<form action="commands.php" onsubmit="return false">
<div class="line" style="text-align:center;">
Execute command on one or all memcached servers<br/>
<hr/>
</div>
<div class="line">
<span class="left">Command</span>
<span class="right">
<select id="request_command" onchange="javascript:changeCommand(this);">
<option value="">Choose a Command</option>
<option value="get">get</option>
<option value="set">set</option>
<option value="delete">delete</option>
<option value="increment">increment</option>
<option value="decrement">decrement</option>
<option value="flush_all">flush all</option>
</select>
</span>
</div>
<div id="div_key" class="line" style="display:none;">
<span class="left">Key</span>
<span class="right">
<input id="request_key"/>
</span>
</div>
<div id="div_duration" class="line" style="display:none;">
<span class="left">Duration</span>
<span class="right">
<input id="request_duration"/>
</span>
</div>
<div id="div_value" class="line" style="display:none;">
<span class="left">Value</span>
<span class="right">
<input id="request_value"/>
</span>
</div>
<div id="div_data" class="line" style="display:none;">
<span class="left">Data</span>
<span class="right">
<textarea id="request_data" rows="2" cols="2"></textarea>
</span>
</div>
<div id="div_delay" class="line" style="display:none;">
<span class="left">Delay</span>
<span class="right">
<input id="request_delay"/>
</span>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('request_server'); ?>
</span>
</div>
<div class="line">
<span class="left">API</span>
<span class="right">
<?php echo Library_HTML_Components::apiList($_ini->get('get_api'), 'request_api'); ?>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:executeCommand('container');javascript:this.blur();" value="Execute Command"/>
</div>
</form>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
Available commands :
<ul>
<li>get : retreive a key value</li>
<li>set : set a key/value pair</li>
<li>delete : delete a specific key</li>
<li>increment : increment a numeric key value</li>
<li>decrement : decrement a numeric key value</li>
<li>flush all : flush a Memcached server</li>
</ul>
<br/>
</td>
</tr>
</table>
</div>
<div class="sub-header corner full-size padding">Execute Telnet <span class="green">Commands</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<div class="line" style="text-align:center;">
Execute telnet command on one or all memcached servers<br/>
<hr/>
</div>
<div class="line" style="text-align:center;">
<textarea id="request_telnet" rows="2" cols="2"></textarea>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('request_telnet_server'); ?>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:executeTelnet('container');javascript:this.blur();" value="Execute Telnet Command"/>
</div>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
You can use this thing to execute any telnet command to any memcached server
<br/>
It will connect to the server, execute the command and return it in the console
<br/>
<br/>
<br/>
<br/>
For more informations about memcached commands, see memcached protocol
<a href="http://github.com/memcached/memcached/blob/master/doc/protocol.txt" target="_blank"><span class="green">here</span></a>
</td>
</tr>
</table>
</div>
<div class="sub-header corner full-size padding">Search <span class="green">Key</span></div>
<div class="container corner full-size padding">
<table>
<tr valign="top">
<td class="size-0 padding" style="padding-right:14px;">
<div class="line" style="text-align:center;">
Search for a key on one or all memcached servers<br/>
<hr/>
</div>
<div class="line">
<span class="left">Key</span>
<span class="right">
<input id="search_key" name="search_key"/>
</span>
</div>
<div class="line">
<span class="left">Server</span>
<span class="right">
<?php echo Library_HTML_Components::serverSelect('search_server'); ?>
</span>
</div>
<div class="line">
<span class="left">Detail Level</span>
<span class="right">
<select id="search_level">
<option value="full">Show Keys, Expiration & Size</option>
<option value="keys">Show Keys</option>
</select>
</span>
</div>
<div class="line">
<span class="left">Action</span>
<span class="right">
<select id="search_more">
<option value="show">Search & Show Keys</option>
<option value="delete">Search & Delete Keys</option>
</select>
</span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="header" type="submit"
onclick="javascript:searchKey('container');javascript:this.blur();" value="Search Key"/>
</div>
</td>
<td class="padding" style="border-left:1px solid #ffffff;padding-left:14px;">
<span class="red">Warning !</span><br/>This thing is only for debuging issue, do not use it in a production environment as it can lock
or impact your memcached servers performances.
<br/>Also keep in mind that it does not list all keys. It lists keys up to a certain buffer size (1 or 2MB), and it list key that are expired.
<br/>
<br/>You can also use a PCRE regular expression
</td>
</tr>
</table>
</div>
</div>

View File

@ -0,0 +1,151 @@
<div style="float:left;">
<div class="size-0" style="float:left;">
<div class="sub-header corner padding">Live Stats <span class="green">Configuration</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=live_stats">
<div class="line">
Alert &amp; refresh rate for Live Stats<br/>
<hr/>
</div>
<div class="line">
<span class="left">Refresh Rate in sec</span>
<span class="right"><input type="text" name="refresh_rate" value="<?php echo $_ini->get('refresh_rate'); ?>"/></span>
</div>
<div class="line">
<span class="left">Memory Alert</span>
<span class="right"><input type="text" name="memory_alert" value="<?php echo $_ini->get('memory_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Hit Rate Alert</span>
<span class="right"><input type="text" name="hit_rate_alert" value="<?php echo $_ini->get('hit_rate_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Eviction Alert</span>
<span class="right"><input type="text" name="eviction_alert" value="<?php echo $_ini->get('eviction_alert'); ?>"/></span>
</div>
<div class="line">
<span class="left">Temp Path</span>
<span class="right"><input type="text" name="file_path" value="<?php echo $_ini->get('file_path'); ?>"/></span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="list" type="submit" value="Save Live Configuration"/>
</div>
</form>
</div>
<div class="sub-header corner padding">Miscellaneous <span class="green">Configuration</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=miscellaneous">
<div class="line">
Server connection timeout &amp; miscellaneous<br/>
<hr/>
</div>
<div class="line">
<span class="left">Timeout in sec</span>
<span class="right"><input type="text" name="connection_timeout" value="<?php echo $_ini->get('connection_timeout'); ?>"/></span>
</div>
<div class="line">
<span class="left">Max Items</span>
<span class="right"><input type="text" name="max_item_dump" value="<?php echo $_ini->get('max_item_dump'); ?>"/></span>
</div>
<div class="line" style="text-align:center;">
<hr/>
<input class="list" type="submit" value="Save API Configuration"/>
</div>
</form>
</div>
</div>
<div class="size-0" style="float:left;padding-left:9px;">
<div class="sub-header corner padding">Server <span class="green">List</span></div>
<div class="container corner padding" style="padding-right:14px;">
<form method="post" action="configure.php?request_write=servers">
<div class="line">
Servers list used by phpMemcacheAdmin<br/><br/>
The server name will be filled by default with hostname:port
</div>
<div id="server_form">
<?php
# Initializing variables
$server_id = 0;
$cluster_id = 0;
# Looking into each cluster
foreach($_ini->get('servers') as $cluster => $servers)
{
$cluster_id++; ?>
<div id="cluster_<?php echo $cluster_id; ?>">
<hr/>
<strong>Cluster <input type="text" style="width:200px;" name="cluster[<?php echo $cluster_id; ?>]" value="<?php echo $cluster; ?>"/></strong>
<div style="margin-left:30px;margin-top:3px;">
<div style="width:150px;float:left;">Name (Optionnal)</div>
<div style="width:150px;float:left;margin-left:7px;">IP/Hostname</div>
<div style="width:50px;float:left;margin-left:7px;">Port</div>
</div>
<?php # Adding input for each server
foreach($servers as $name => $server)
{
$server_id++; ?>
<div id="server_<?php echo $server_id; ?>">
<div style="margin-left:30px;margin-top:3px;">
<input type="text" style="width:150px;" name="server[<?php echo $cluster_id; ?>][<?php echo $server_id; ?>][name]"
value="<?php echo $name; ?>"
id="name_<?php echo $server_id; ?>"
onchange="nameOnChange(<?php echo $server_id; ?>)"/>
<input type="text" style="width:150px;" name="server[<?php echo $cluster_id; ?>][<?php echo $server_id; ?>][hostname]"
value="<?php echo $server['hostname']; ?>"
id="host_<?php echo $server_id; ?>"
<?php # Custom name
if ($name == $server['hostname'] . ':' . $server['port']) { ?>
onchange="hostOrPortOnChange(<?php echo $server_id; ?>)"
onKeyUp="hostOrPortOnChange(<?php echo $server_id; ?>)"
<?php
} ?>
onfocus="hostOnFocus(this)"
onblur="hostOnBlur(this)"/>
<input type="text" style="width:50px;" name="server[<?php echo $cluster_id; ?>][<?php echo $server_id; ?>][port]"
value="<?php echo $server['port']; ?>"
id="port_<?php echo $server_id; ?>"
<?php # Custom name
if ($name == $server['hostname'] . ':' . $server['port']) { ?>
onchange="hostOrPortOnChange(<?php echo $server_id; ?>)"
onKeyUp="hostOrPortOnChange(<?php echo $server_id; ?>)"
<?php
} ?>
onfocus="portOnFocus(this)"
onblur="portOnBlur(this)"/>
<a class="list button" style="padding:1px 2px;" href="#" onclick="deleteServerOrCluster('server_<?php echo $server_id; ?>')">Delete</a>
</div>
</div>
<?php } ?>
<div id="cluster_<?php echo $cluster_id; ?>_commands" style="margin-left:40px;margin-top:6px;">
<a class="list button" href="javascript:addServer(<?php echo $cluster_id; ?>)">Add New Server to Cluster</a>
<a class="list" style="padding:1px 2px;-moz-border-radius:3px;-webkit-border-radius:3px;" href="#"
onclick="deleteServerOrCluster('cluster_<?php echo $cluster_id; ?>')">Delete Cluster</a>
</div>
<br/>
</div>
<?php } ?>
</div>
<div class="line">
<hr/>
<a class="list button" href="javascript:addCluster()">Add New Cluster</a>
<input class="list" type="submit" value="Save Servers Configuration"/>
</div>
</form>
</div>
<script type="text/javascript">
server_id = <?php echo $server_id; ?>;
cluster_id = <?php echo $cluster_id; ?>;
</script>
<div class="container corner padding" style="margin-top:10px;">
<div class="line">
For more information about configuring phpMemcachedAdmin, see installation guide
<a href="https://blog.elijaa.org/phpmemcachedadmin-installation-guide/" target="_blank"><span class="green">here</span></a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,18 @@
<?php
# Check for newer version
if(Library_Data_Version::check())
{ ?>
<div class="header corner full-size padding" style="float:left; text-align:center; margin-top:10px;">
A newer version of phpMemcachedAdmin may be available, visit <a href="https://blog.elijaa.org/phpmemcachedadmin-download/" target="_blank">PHPMemcachedAdmin Blog</a> to know more.
<?php
} else { ?>
<div class="sub-header corner full-size padding" style="float:left; text-align:center; margin-top:10px;">
<a href="https://github.com/elijaa/phpmemcachedadmin" target="_blank">PHPMemcachedAdmin on GitHub</a> -
<a href="https://blog.elijaa.org" target="_blank">PHPMemcachedAdmin Blog</a> -
<a href="http://memcached.org" target="_blank">Memcached.org</a>
<?php
} ?>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,62 @@
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>PHPMemcachedAdmin <?php echo CURRENT_VERSION; ?></title>
<link rel="stylesheet" type="text/css" href="Public/Styles/Style.css"/>
<script type="text/javascript" src="Public/Scripts/Highcharts/highcharts.js"></script>
<script type="text/javascript" src="Public/Scripts/script.js"></script>
</head>
<body>
<div style="margin:0pt auto; width:1000px; clear:both;">
<div style="font-weight:bold;font-size:1.2em;">PHPMemcachedAdmin <sup><?php echo CURRENT_VERSION; ?></sup>
</div>
<div class="header corner full-size padding" style="text-align:center;margin-top:5px;">
<?php
# Live Stats view
if(basename($_SERVER['PHP_SELF']) == 'stats.php')
{ ?>
Live Stats |
<?php
} else { ?>
<a href="stats.php">See Live Stats </a> |
<?php
}
# Stats view
if(basename($_SERVER['PHP_SELF']) == 'index.php')
{ ?>
Actually seeing
<?php
} else { ?>
<a href="index.php">See Stats for </a>
<?php
}
# Server HTML select
echo Library_HTML_Components::serverSelect('server_select', (isset($_REQUEST['server'])) ? $_REQUEST['server'] : '', 'list', 'onchange="changeServer(this)"'); ?>
|
<?php
# Commands view
if(basename($_SERVER['PHP_SELF']) == 'commands.php')
{ ?>
Executing Commands on Servers
<?php
} else { ?>
<a href="commands.php">Execute Commands on Servers</a>
<?php
}?>
</div>
<?php
if (is_writable($_ini->get('file_path')) === false) {
?>
<div class="header corner full-size padding" style="margin-top:10px;">
Warning : Temporary directory '<em><?php echo $_ini->get('file_path') ?></em>' is not writable, please fix this error and try again.
</div>
<?php
}
?>
<!--[if IE]>
<div class="header corner full-size padding" style="text-align:center;margin-top:10px;">
Support browsers that contribute to open source, try <a href="http://www.firefox.com" target="_blank">Firefox</a> or <a href="http://www.google.com/chrome" target="_blank">Google Chrome</a>.
</div>
<![endif]-->

View File

@ -0,0 +1,70 @@
<script type="text/javascript">
var timeout = <?php echo $refresh_rate * 1000; ?>;
var page = 'stats.php?request_command=live_stats&cluster=<?php echo $cluster; ?>';
setTimeout("ajax(page,'stats')", <?php echo (5 + $refresh_rate - $_ini->get('refresh_rate')) * 1000; ?>);
</script>
<div style="float:left;">
<div class="sub-header corner full-size padding">Live <span class="green">Stats</span></div>
<?php
# Refresh rate increased
if($refresh_rate > $_ini->get('refresh_rate'))
{ ?>
<div class="container corner" style="padding:9px;">
Connections errors were discovered, to prevent any problem, refresh rate was increased by
<?php echo sprintf('%.1f', $refresh_rate - $_ini->get('refresh_rate')); ?> seconds.
</div>
<?php
} ?>
<div class="full-size padding">
<br/>
<span class="live">Actually looking at <?php echo Library_HTML_Components::clusterSelect('cluster_select', (isset($_REQUEST['cluster'])) ? $_REQUEST['cluster'] : '', 'live', 'onchange="changeCluster(this);"'); ?> stats</span>
<pre id="stats" class="live">
Loading live stats, please wait ~<?php echo sprintf('%.0f', 5 + $refresh_rate - $_ini->get('refresh_rate')); ?> seconds ...
</pre>
</div>
<div class="container corner full-size padding">
<div class="line">
<span class="left setting">SIZE</span>
Total cache size on this server
</div>
<div class="line">
<span class="left setting">%MEM</span>
Percentage of total cache size used on this server
</div>
<div class="line">
<span class="left setting">%HIT</span>
Global hit percent on this server : get_hits / (get_hits + get_misses)
</div>
<div class="line">
<span class="left setting">TIME</span>
Time taken to connect to the server and proceed the request, high value can indicate a latency or server problem
</div>
<div class="line">
<span class="left setting">REQ/s</span>
Total request per second (get, set, delete, incr, ...) issued to this server
</div>
<div class="line">
<span class="left setting">CONN</span>
Current connections, monitor that this number doesn't come too close to the server max connection setting
</div>
<div class="line">
<span class="left setting">GET/s, SET/s, DEL/s</span>
Get, set or delete commands per second issued to this server
</div>
<div class="line">
<span class="left setting">EVI/s</span>
Number of times an item which had an explicit expire time set had to be evicted before it expired
</div>
<div class="line">
<span class="left setting">READ/s</span>
Total number of bytes read by this server from network
</div>
<div class="line">
<span class="left setting">WRITE/s</span>
Total number of bytes sent by this server to network
</div>
</div>
</div>

View File

@ -0,0 +1,87 @@
<?php
# CRLF/EOL
define('EOL', "\r\n");
# Header
echo 'Last update : ' . date('r', time()) . ' (refresh rate : ' . $_ini->get('refresh_rate') . ' sec)' . EOL . EOL;
# Table header
echo '<strong>' . sprintf('%-36s', 'NAME') . sprintf('%10s', 'SIZE') . sprintf('%7s', '%MEM') . sprintf('%8s', 'TIME') .
sprintf('%6s', 'CONN') . sprintf('%7s', '%HIT') . sprintf('%8s', 'REQ/s') . sprintf('%8s', 'GET/s') . sprintf('%8s', 'SET/s') .
sprintf('%8s', 'DEL/s') . sprintf('%8s', 'EVI/s') . sprintf('%11s', 'READ/s') . sprintf('%10s', 'WRITE/s') . '</strong>' . EOL . '<hr>';
# Showing stats for every server
foreach($stats as $server => $data)
{
# Server name
echo sprintf('%-36.36s', $server);
# Checking for stats validity
if((isset($data['time'], $data['bytes_percent'], $data['get_hits_percent'], $data['query_time'], $data['request_rate'], $data['curr_connections'],
$data['get_rate'], $data['set_rate'], $data['delete_rate'], $data['eviction_rate'], $data['bytes_read'], $data['bytes_written'])) && ($data['time'] > 0))
{
# Total Memory
echo sprintf('%10s', Library_Data_Analysis::byteResize($data['limit_maxbytes']) . 'b');
# Memory Occupation / Alert State
if($data['bytes_percent'] > $_ini->get('memory_alert'))
{
echo str_pad('', 7 - strlen($data['bytes_percent']), ' ') . '<span class="red">' . sprintf('%.1f', $data['bytes_percent']) . '</span>';
}
else
{
echo sprintf('%7.1f', $data['bytes_percent']);
}
# Query Time
echo sprintf('%5.0f', Library_Data_Analysis::valueResize($data['query_time'])) . ' ms';
# Current connection
echo sprintf('%6s', $data['curr_connections']);
# Hit percent (get)
if($data['get_hits_percent'] < $_ini->get('hit_rate_alert'))
{
echo str_pad('', 7 - strlen($data['get_hits_percent']), ' ') . '<span class="red">' . sprintf('%.1f', $data['get_hits_percent']) . '</span>';
}
else
{
echo sprintf('%7.1f', $data['get_hits_percent']);
}
# Request rate
echo sprintf('%8s', Library_Data_Analysis::valueResize($data['request_rate']));
# Get rate
echo sprintf('%8s', Library_Data_Analysis::valueResize($data['get_rate']));
# Set rate
echo sprintf('%8s', Library_Data_Analysis::valueResize($data['set_rate']));
# Delete rate
echo sprintf('%8s', Library_Data_Analysis::valueResize($data['delete_rate']));
# Eviction rate
if($data['eviction_rate'] > $_ini->get('eviction_alert'))
{
echo str_pad('', 8 - strlen(Library_Data_Analysis::valueResize($data['eviction_rate'])), ' ') . '<span class="red">' . Library_Data_Analysis::valueResize($data['eviction_rate']) . '</span>';
}
else
{
echo sprintf('%8s', Library_Data_Analysis::valueResize($data['eviction_rate']));
}
# Bytes read
echo sprintf('%11s', Library_Data_Analysis::byteResize($data['bytes_read'] / $data['time']) . 'b');
# Bytes written
echo sprintf('%10s', Library_Data_Analysis::byteResize($data['bytes_written'] / $data['time']) . 'b');
}
else
{
echo str_pad('', 20, ' ') . '<span class="alert">An error has occured when retreiving or calculating stats</span>';
}
# End of Line
echo EOL . '<hr>';
}

View File

@ -0,0 +1,58 @@
<?php
# Server seems down
if((isset($stats)) && (($stats === false) || ($stats == array())))
{ ?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
<?php
# Asking server of cluster stats
if(isset($_REQUEST['server']))
{
echo ($_ini->cluster($_REQUEST['server'])) ? 'All servers from Cluster ' . $_REQUEST['server'] : 'Server ' . $_REQUEST['server'], ' did not respond !';
}
# All servers stats
else
{
echo 'Servers did not respond !';
} ?>
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
<?php echo Library_Data_Error::last(); ?>
<br/>
<br/>
Please check above error message, your <a href="configure.php" class="green">configuration</a> or your server status and retry
</div>
<?php
}
# No slabs used
elseif((isset($slabs)) && ($slabs === false))
{
?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
No slabs used in this server !
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
Maybe this server is not used, check your <a href="configure.php" class="green">configuration</a> or your server status and retry
</div>
<?php
}
# No Items in slab
elseif((isset($items)) && ($items === false))
{
?>
<div class="header corner full-size padding" style="margin-top:10px;text-align:center;">
No item in this slab !
</div>
<div class="container corner full-size padding">
<span class="left">Error message</span>
<br/>
This slab is allocated, but is empty
<br/>
<br/>
Go back to <a href="?server=<?php echo $_REQUEST['server']; ?>&amp;show=slabs" class="green">Server Slabs</a>
</div>
<?php
}

View File

@ -0,0 +1,56 @@
<div class="sub-header corner full-size padding">Console</div>
<div class="container corner full-size padding" id="console" style="visibility:visible;display:block;">
<pre id="container" style="font-size:11px;overflow:auto;min-height:80px;max-height:196px;" class="full-size">
Click on an item's key below to see it's content here
</pre>
</div>
<div class="container corner full-size padding" style="text-align:right;">
<span style="float:left;">
<input style="witdh:200px;" class="header loading" type="submit" id="loading" value="Waiting for server response ..."/>
</span>
<input class="header" type="submit" onclick="javascript:executeClear('container')" value="Clear Console"/>
<input class="header" id="hide" type="submit" onclick="javascript:executeHideShow('console', 'hide');javascript:this.blur();" value="Hide Console"/>
</div>
<div class="sub-header corner full-size padding">
Items in Slab <?php echo $_REQUEST['slab']; ?>, only showing first <?php echo $_ini->get('max_item_dump'); ?> items
<span style="float:right;">
<a href="?server=<?php echo $_REQUEST['server']; ?>&amp;show=slabs">Back to Server Slabs</a>
</span>
</div>
<div class="container corner full-size padding">
<?php
$notFirst = false;
# Items
foreach($items as $key => $data)
{
# Checking if first item
if($notFirst) { echo '<hr/>'; }
?>
<a class="green item" style=""
onclick="javascript:executeHideShow('console', 'hide', true);javascript:executeCommand('container', 'request_key=<?php echo urlencode($key); ?>&amp;request_api=<?php echo $_ini->get('get_api'); ?>&amp;request_command=get&amp;request_server=<?php echo $_REQUEST['server']; ?>');"><?php echo ((strlen($key) > 70) ? substr($key, 0, 70) . '[..]' : $key); ?></a>
<span class="right" style="clear:right;">
<strong>Size</strong> : <?php echo Library_Data_Analysis::byteResize($data[0]); ?>Bytes,
<strong>Expiration</strong> :
<?php
# Infinite expiration
if($data[1] == $infinite)
{
echo '&#8734;';
}
# Timestamp expiration
else
{
echo Library_Data_Analysis::uptime($data[1] - time());
} ?>
</span>
<?php
# First item done
$notFirst = true;
} ?>
</div>

View File

@ -0,0 +1,126 @@
<div class="size-4" style="float:left;">
<div class="sub-header corner padding">Slabs <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Slabs Used</span>
<?php echo $slabs['active_slabs']; ?>
</div>
<div class="line">
<span class="left">Memory Used</span>
<?php echo Library_Data_Analysis::byteResize($slabs['total_malloced']); ?>Bytes
</div>
<div class="line">
<span class="left">Wasted</span>
<?php echo Library_Data_Analysis::byteResize($slabs['total_wasted']); ?>Bytes
</div>
</div>
</div>
<div class="size-2" style="float:left;padding-left:9px;margin-top:10px;">
<div class="header corner padding size-3cols" style="text-align:center;">
<a href="?server=<?php echo $_REQUEST['server']; ?>">See this Server Stats</a>
</div>
<br/>
</div>
<div class="size-1" style="float:left;padding-left:9px;">
<div class="container corner" style="padding:9px;">
For more informations about memcached slabs stats, see memcached protocol
<a href="http://github.com/memcached/memcached/blob/master/doc/protocol.txt#L470" target="_blank"><span class="green">here</span></a>
</div>
</div>
<table class="full-size" cellspacing="0" cellpadding="0">
<tr>
<?php
$actualSlab = 0;
# Slabs parsing
foreach($slabs as $id => $slab)
{
# If Slab is Used
if(is_numeric($id))
{
# Making a new line
if($actualSlab >= 4)
{
?>
</tr>
<tr>
<?php
$actualSlab = 0;
}
?>
<td <?php if($actualSlab > 0) { echo 'style="padding-left:9px;"'; } ?> valign="top">
<div class="sub-header corner padding size-5">Slab <?php echo $id; ?> <span class="green">Stats</span>
<span style="float:right;"><a href="?server=<?php echo $_REQUEST['server']; ?>&amp;show=items&amp;slab=<?php echo $id; ?>">See Slab Items</a></span>
</div>
<div class="container corner padding size-5">
<div class="line">
<span class="left slabs">Chunk Size</span>
<?php echo Library_Data_Analysis::byteResize($slab['chunk_size']); ?>Bytes
</div>
<div class="line">
<span class="left slabs">Used Chunk</span>
<?php echo Library_Data_Analysis::hitResize($slab['used_chunks']); ?>
<span class="right">[<?php echo Library_Data_Analysis::valueResize($slab['used_chunks'] / $slab['total_chunks'] * 100); ?> %]</span>
</div>
<div class="line">
<span class="left slabs">Total Chunk</span>
<?php echo Library_Data_Analysis::hitResize($slab['total_chunks']); ?>
</div>
<div class="line">
<span class="left slabs">Total Page</span>
<?php echo $slab['total_pages']; ?>
</div>
<div class="line">
<span class="left slabs">Wasted</span>
<?php echo Library_Data_Analysis::byteResize($slab['mem_wasted']); ?>Bytes
</div>
<div class="line">
<span class="left slabs">Hits</span>
<?php echo ($slab['request_rate'] > 999) ? Library_Data_Analysis::hitResize($slab['request_rate']) : $slab['request_rate']; ?> Request/sec
</div>
<?php
if($slab['used_chunks'] > 0)
{ ?>
<div class="line">
<span class="left slabs">Evicted</span>
<?php echo (isset($slab['items:evicted'])) ? $slab['items:evicted'] : 'N/A'; ?>
</div>
<!--
<div class="line">
<span class="left slabs">Evicted Last</span>
<?php echo Library_Data_Analysis::uptime($slab['items:evicted_time']); ?>
</div>
<div class="line">
<span class="left slabs">Out of Memory</span>
<?php echo $slab['items:outofmemory']; ?>
</div>
<div class="line">
<span class="left slabs">Tail Repairs</span>
<?php echo $slab['items:tailrepairs']; ?>
</div>
-->
<?php }
else
{?>
<div class="line">
<span class="left slabs">Slab is allocated but empty</span>
</div>
<?php } ?>
</div>
</td>
<?php
$actualSlab++;
}
?>
<?php
}
for(true; $actualSlab < 4 ; $actualSlab++)
{
echo '<td style="width:100%;"></td>';
}
?>
</tr>
</table>

View File

@ -0,0 +1,551 @@
<div class="size-4" style="float:left;">
<div class="sub-header corner padding">Get <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo Library_Data_Analysis::hitResize($stats['get_hits']); ?>
<span class="right">[<?php echo $stats['get_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo Library_Data_Analysis::hitResize($stats['get_misses']); ?>
<span class="right">[<?php echo $stats['get_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo $stats['get_rate']; ?> Request/sec
</div>
</div>
<div class="sub-header corner padding">Set <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Total</span>
<?php echo Library_Data_Analysis::hitResize($stats['cmd_set']); ?>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo $stats['set_rate']; ?> Request/sec
</div>
</div>
<div class="sub-header corner padding">Delete <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['delete_hits'])) ? Library_Data_Analysis::hitResize($stats['delete_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['delete_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['delete_misses'])) ? Library_Data_Analysis::hitResize($stats['delete_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['delete_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['delete_hits'])) ? $stats['delete_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Cas <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['cas_hits'])) ? Library_Data_Analysis::hitResize($stats['cas_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['cas_misses'])) ? Library_Data_Analysis::hitResize($stats['cas_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Bad Value</span>
<?php echo (isset($stats['cas_badval'])) ? Library_Data_Analysis::hitResize($stats['cas_badval']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['cas_badval_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['cas_hits'])) ? $stats['cas_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Increment <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['incr_hits'])) ? Library_Data_Analysis::hitResize($stats['incr_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['incr_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['incr_misses'])) ? Library_Data_Analysis::hitResize($stats['incr_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['incr_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['incr_hits'])) ? $stats['incr_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Decrement <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['decr_hits'])) ? Library_Data_Analysis::hitResize($stats['decr_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['decr_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['decr_misses'])) ? Library_Data_Analysis::hitResize($stats['decr_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['decr_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['decr_hits'])) ? $stats['decr_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Touch <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Hits</span>
<?php echo (isset($stats['touch_hits'])) ? Library_Data_Analysis::hitResize($stats['touch_hits']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['touch_hits_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Miss</span>
<?php echo (isset($stats['touch_misses'])) ? Library_Data_Analysis::hitResize($stats['touch_misses']) : 'N/A on ' . $stats['version']; ?>
<span class="right">[<?php echo $stats['touch_misses_percent']; ?>%]</span>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['touch_hits'])) ? $stats['touch_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<div class="sub-header corner padding">Flush <span class="green">Stats</span></div>
<div class="container corner padding" style="height:48px;">
<div class="line">
<span class="left">Total</span>
<?php echo (isset($stats['cmd_flush'])) ? Library_Data_Analysis::hitResize($stats['cmd_flush']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left">Rate</span>
<?php echo (isset($stats['cmd_flush'])) ? $stats['flush_rate'] . ' Request/sec' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
</div>
<div class="size-2" style="float:left;padding-left:9px;">
<?php
# Viewing a single server
if((isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])))
{ ?>
<div class="header corner padding size-3cols" style="text-align:center;margin-top:10px;">
<a href="?server=<?php echo $_REQUEST['server']; ?>&amp;show=slabs">See this Server Slabs Stats</a>
</div>
<?php
} ?>
<div class="sub-header corner padding"><?php echo (isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])) ? 'Server' : 'Cluster'; ?> <span class="green">Stats</span></div>
<div class="container corner padding size-3cols">
<?php
# Viewing a single server
if((isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])))
{ ?>
<div class="line">
<span class="left setting">Uptime</span>
<?php echo Library_Data_Analysis::uptime($stats['uptime']); ?>
</div>
<div class="line" style="margin-bottom:4px;">
<span class="left setting">Memcached</span>
Version <?php echo $stats['version']; ?>
</div>
<?php
} ?>
<div class="line">
<span class="left setting">Curr Connections</span>
<?php echo $stats['curr_connections']; ?>
</div>
<div class="line">
<span class="left setting">Total Connections</span>
<?php echo Library_Data_Analysis::hitResize($stats['total_connections']); ?>
</div>
<div class="line">
<span class="left setting">Max Connections Errors</span>
<?php echo (isset($stats['listen_disabled_num'])) ? Library_Data_Analysis::hitResize($stats['listen_disabled_num']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line" style="margin-top:4px;">
<span class="left setting">Current Items</span>
<?php echo Library_Data_Analysis::hitResize($stats['curr_items']); ?>
</div>
<div class="line">
<span class="left setting">Total Items</span>
<?php echo Library_Data_Analysis::hitResize($stats['total_items']); ?>
</div>
<?php
# Viewing a single server
if((isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])))
{ ?>
<div class="line">
<span class="left setting">Oldest Item</span>
<?php echo (isset($settings['oldest'])) ? Library_Data_Analysis::uptime($settings['oldest']) : 'N/A on ' . $stats['version']; ?>
</div>
<?php
} ?>
</div>
<div class="sub-header corner padding">Eviction &amp; Reclaimed <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left setting">Items Eviction</span>
<?php echo Library_Data_Analysis::hitResize($stats['evictions']); ?>
</div>
<div class="line">
<span class="left setting">Rate</span>
<?php echo $stats['eviction_rate']; ?> Eviction/sec
</div>
<div class="line" style="margin-top:4px;">
<span class="left setting">Reclaimed</span>
<?php echo (isset($stats['reclaimed'])) ? Library_Data_Analysis::hitResize($stats['reclaimed']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting">Rate</span>
<?php echo (isset($stats['reclaimed'])) ? $stats['reclaimed_rate'] . ' Reclaimed/sec' : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line" style="margin-top:4px;">
<span class="left setting help" title="Internal name : expired_unfetched&#013;Items pulled from LRU that were never touched by get/incr/append/etc before expiring">Expired unfetched</span>
<?php echo (isset($stats['expired_unfetched'])) ? Library_Data_Analysis::hitResize($stats['expired_unfetched']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : evicted_unfetched&#013;Items evicted from LRU that were never touched by get/incr/append/etc">Evicted unfetched</span>
<?php echo (isset($stats['evicted_unfetched'])) ? Library_Data_Analysis::hitResize($stats['evicted_unfetched']) : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<?php
# Viewing a server
if((isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])))
{ ?>
<div class="sub-header corner padding">Server <span class="green">Configuration</span></div>
<div class="container corner padding">
<div class="line">
<span class="left setting help" title="Internal name : accepting_conns&#013;Whether the server is accepting connection or not">Accepting Connections</span>
<?php
# Northscale/Membase server specific
if(isset($stats['accepting_conns']))
{
if($stats['accepting_conns']) { echo 'Yes'; } else { echo 'No'; }
}
else
{
echo 'N/A on ' . $stats['version'];
}?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : maxbytes&#013;Maximum number of bytes allowed in this cache">Max Bytes</span>
<?php echo (isset($settings['maxbytes'])) ? Library_Data_Analysis::byteResize($settings['maxbytes']) . 'Bytes' : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : maxconns&#013;Maximum number of clients allowed">Max Connection</span>
<?php echo (isset($settings['maxconns'])) ? $settings['maxconns'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : tcpport &amp; udpport&#013;TCP &amp; UDP listen port">TCP/UDP Port</span>
<?php echo (isset($settings['tcpport'], $settings['udpport'])) ? 'TCP : ' . $settings['tcpport'] . ', UDP : ' . $settings['udpport'] : 'N/A on ' . $stats['version'] ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : inter&#013;Listen interface">Listen Interface</span>
<?php echo (isset($settings['inter'])) ? $settings['inter'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : evictions&#013;When Off, LRU evictions are disabled">Evictions</span>
<?php echo (isset($settings['evictions'])) ? ucfirst($settings['evictions']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : domain_socket&#013;Path to the domain socket (if any)">Path to Domain Socket</span>
<?php echo (isset($settings['domain_socket'])) ? $settings['domain_socket'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : umask&#013;Umask for the creation of the domain socket">Domain Socket Umask</span>
<?php echo (isset($settings['umask'])) ? $settings['umask'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : chunk_size&#013;Minimum space allocated for key + value + flags">Chunk Size</span>
<?php echo (isset($settings['chunk_size'])) ? $settings['chunk_size'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : growth_factor&#013;Chunk size growth factor">Chunk Growth Factor</span>
<?php echo (isset($settings['growth_factor'])) ? $settings['growth_factor'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : num_threads&#013;Number of threads (including dispatch)">Max Threads</span>
<?php echo (isset($settings['num_threads'])) ? $settings['num_threads'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : detail_enabled&#013;If yes, stats detail is enabled">Detail Enabled</span>
<?php echo (isset($settings['detail_enabled'])) ? ucfirst($settings['detail_enabled']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : reqs_per_event&#013;Max num IO ops processed within an event">Max IO Ops/Event</span>
<?php echo (isset($settings['reqs_per_event'])) ? $settings['reqs_per_event'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : cas_enabled&#013;When no, CAS is not enabled for this server">CAS Enabled</span>
<?php echo (isset($settings['cas_enabled'])) ? ucfirst($settings['cas_enabled']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : tcp_backlog&#013;TCP listen backlog">TCP Listen Backlog</span>
<?php echo (isset($settings['tcp_backlog'])) ? $settings['tcp_backlog'] : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left setting help" title="Internal name : auth_enabled_sasl&#013;SASL auth requested and enabled">SASL Auth</span>
<?php echo (isset($settings['auth_enabled_sasl'])) ? ucfirst($settings['auth_enabled_sasl']) : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<?php
}
# Viewing a cluster
elseif((isset($_REQUEST['server'])) && ($cluster = $_ini->cluster($_REQUEST['server'])))
{ ?>
<div class="sub-header corner padding">Cluster <?php echo $_REQUEST['server']; ?> <span class="green">Servers List</span></div>
<div class="container corner padding">
<?php
# Displaying first 8 servers
$displayed = 0;
foreach($cluster as $name => $server)
{ ?>
<div class="line server" style="<?php if($displayed > 8) { echo 'display:none;'; } else { $displayed++; } ?>">
<span class="left setting"><?php echo (strlen($name) > 27) ? substr($name, 0, 27) . ' [...]' : $name; ?></span>
<span class="right" style="font-weight:bold;"><a href="index.php?server=<?php echo $name; ?>" class="green">See Server Stats</a></span>
<div class="line" style="margin-left:5px;">
<?php echo ($status[$name] != '') ? 'Version ' . $status[$name] . ', Uptime : ' . Library_Data_Analysis::uptime($uptime[$name]) : 'Server did not respond'; ?>
</div>
</div>
<?php
}
# Displaying remaining X server line
$remaining = (count($cluster) - $displayed);
if(($displayed > 8) && ($remaining >= 0))
{ ?>
<div class="line more">
<span class="left" style="font-weight:bold;">
<?php echo $remaining; ?> Server<?php echo ($remaining > 1) ? 's are' : ' is'; ?> not displayed</span>
<span class="right" style="font-weight:bold;"><a href="#" onclick="javascript:show('server');javascript:hide('more');" class="green">See all <?php echo count($cluster); ?> Servers</a></span>
</div>
<?php
} ?>
</div>
<?php
} ?>
</div>
<?php
# Fixing issue 163, some results from stats slabs mem_requested are buggy @FIXME
if($slabs['total_malloced'] > $stats['limit_maxbytes'])
{
$slabs['total_wasted'] = $stats['limit_maxbytes'] - ($slabs['total_malloced'] - $slabs['total_wasted']);
$slabs['total_malloced'] = $stats['limit_maxbytes'];
}
# Making cache size stats
$wasted_percent = sprintf('%.1f', $slabs['total_wasted'] / $stats['limit_maxbytes'] * 100);
$used_percent = sprintf('%.1f', ($slabs['total_malloced'] - $slabs['total_wasted']) / $stats['limit_maxbytes'] * 100);
$free_percent = sprintf('%.1f', ($stats['limit_maxbytes'] - $slabs['total_malloced']) / $stats['limit_maxbytes'] * 100);
?>
<div class="size-4" style="float:left; padding-left:9px;clear:right;">
<div class="sub-header corner padding">Cache Size <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Used</span>
<?php echo Library_Data_Analysis::byteResize($slabs['total_malloced']); ?>Bytes
</div>
<div class="line">
<span class="left">Total</span>
<?php echo Library_Data_Analysis::byteResize($stats['limit_maxbytes']); ?>Bytes
</div>
<div class="line">
<span class="left">Wasted</span>
<?php echo Library_Data_Analysis::byteResize($slabs['total_wasted']); ?>Bytes
</div>
<!--
<div class="line">
<span class="left">Percent</span>
<?php echo sprintf('%.1f', $stats['bytes'] / $stats['limit_maxbytes'] * 100, 1); ?>%
</div>-->
</div>
<div class="sub-header corner padding">Cache Size <span class="green">Graphic</span></div>
<div class="container corner padding">
<div id="cacheUsageContainer"></div>
<script>
new Highcharts.Chart({
chart: {
backgroundColor: '#EBEBEB',
plotBorderWidth: null,
plotShadow: false,
width: 274,
height: 234,
marginLeft: 0,
marginRight: 0,
marginTop: 0,
marginBottom: 0,
renderTo: 'cacheUsageContainer'
},
title: {
text: '<b><?php echo Library_Data_Analysis::byteResize($stats['limit_maxbytes']); ?>Bytes</b>',
y: 110,
style: {
fontSize: '12px'
}
},
tooltip: {
enabled: false
},
plotOptions: {
pie: {
borderWidth: 0,
allowPointSelect: false,
dataLabels: {
enabled: true,
color: '#000000',
distance: 15,
connectorWidth: 1.5,
format: '<b>{point.name}</b><br/>{point.percentage:.1f} %'
},
center: ['50%', '50%']
}
},
credits: {
enabled: false
},
series: [{
type: 'pie',
name: 'Cache Size',
size: '70%',
innerSize: '55%',
data: [{name: 'Wasted',
y: <?php echo $wasted_percent; ?>,
color: '#B5463F'},
{name: 'Used',
y: <?php echo $used_percent; ?>,
color: '#2A707B'},
{name: 'Free',
y: <?php echo $free_percent; ?>,
color: '#FFFFFF'}]
}]
});
</script>
</div>
<?php
# Viewing a single server
if((isset($_REQUEST['server'])) && ($_ini->server($_REQUEST['server'])))
{ ?>
<div class="sub-header corner padding">Hash Table <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left help" title="Internal name : hash_power_level&#013;Current size multiplier for hash table">Power Level</span>
<?php echo (isset($stats['hash_power_level'])) ? Library_Data_Analysis::byteResize($stats['hash_power_level']) . 'Bytes' : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left">Size</span>
<?php echo (isset($stats['hash_bytes'])) ? Library_Data_Analysis::byteResize($stats['hash_bytes']) . 'Bytes' : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left help" title="Internal name : hash_is_expanding&#013;Indicates if the hash table is being grown to a new size">Expanding</span>
<?php if(isset($stats['hash_is_expanding'])) { if($stats['hash_is_expanding']) { echo 'Yes'; } else { echo 'No'; } } else { echo 'N/A on ' . $stats['version']; } ?>
</div>
</div>
<?php
}
# Viewing a cluster
elseif((isset($_REQUEST['server'])) && ($cluster = $_ini->cluster($_REQUEST['server'])))
{ ?>
<div class="sub-header corner padding">Hash Table <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Size</span>
<?php echo (isset($stats['hash_bytes'])) ? Library_Data_Analysis::byteResize($stats['hash_bytes']) . 'Bytes' : 'N/A on ' . $stats['version']; ?>
</div>
</div>
<?php
} ?>
<div class="sub-header corner padding">Slab <span class="green">Reassign & Automove</span></div>
<div class="container corner padding">
<div class="line">
<span class="left help" title="Internal name : slabs_moved&#013;Indicates how many pages have been successfully moved">Slabs Moved</span>
<?php echo (isset($stats['slabs_moved'])) ? Library_Data_Analysis::hitResize($stats['slabs_moved']) : 'N/A on ' . $stats['version']; ?>
</div>
<div class="line">
<span class="left help" title="Internal name : slab_reassign_running&#013;Indicates if the slab thread is attempting to move a page.&#013;It may need to wait for some memory to free up, so it could take several seconds.">Reassigning</span>
<?php if(isset($stats['slab_reassign_running'])) { if($stats['slab_reassign_running']) { echo 'Yes'; } else { echo 'No'; } } else { echo 'N/A on ' . $stats['version']; } ?>
</div>
</div>
<div class="sub-header corner padding">Hit &amp; Miss Rate <span class="green">Graphic</span></div>
<div class="container corner padding">
<div id="hitsContainer"></div>
<script>
new Highcharts.Chart({
chart: {
backgroundColor: '#EBEBEB',
width: 274,
height: 147,
marginLeft: 0,
marginRight: 0,
marginTop: 0,
marginBottom: 20,
renderTo: 'hitsContainer'
},
title: {
text: null
},
tooltip: {
enabled: false
},
plotOptions: {
column: {
dataLabels: {
enabled: true,
format: '<b>{y} %</b>'
}
}
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
categories: ['Hits', 'Misses']
},
yAxis: {
gridLineWidth: 0
},
series: [{
type: 'column',
name: 'Cache Size',
data: [{name: 'Hits',
y: <?php echo $stats['get_hits_percent']; ?>,
color: '#2A707B'},
{name: 'Misses',
y: <?php echo $stats['get_misses_percent']; ?>,
color: '#B5463F'}]
}]
});
</script>
</div>
<div class="sub-header corner padding">Network <span class="green">Stats</span></div>
<div class="container corner padding">
<div class="line">
<span class="left">Bytes Read</span>
<?php echo Library_Data_Analysis::byteResize($stats['bytes_read']); ?>Bytes
</div>
<div class="line">
<span class="left">Bytes Written</span>
<?php echo Library_Data_Analysis::byteResize($stats['bytes_written']); ?>Bytes
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More