From a4104d7c17242c5f583891df7ed1f10f3ca94de2 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Tue, 17 Nov 2015 11:34:47 +0100 Subject: [PATCH 01/24] 1st stuff for federation stats in the admin panel --- mod/admin.php | 53 +++++++++++++++++++++++-- view/global.css | 6 +++ view/templates/admin_aside.tpl | 10 ++--- view/templates/admin_federation.tpl | 60 +++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 view/templates/admin_federation.tpl diff --git a/mod/admin.php b/mod/admin.php index 0636a3420..886d7a4d9 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -121,15 +121,17 @@ function admin_content(&$a) { /** * Side bar links */ - + $aside = Array(); // array( url, name, extra css classes ) - $aside = Array( + // not part of $aside to make the template more adjustable + $asidesubpages = Array( 'site' => Array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"), 'users' => Array($a->get_baseurl(true)."/admin/users/", t("Users") , "users"), 'plugins'=> Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"), 'themes' => Array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"), 'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"), 'queue' => Array($a->get_baseurl(true)."/admin/queue/", t('Inspect Queue'), "queue"), + 'federation' => Array($a->get_baseurl(true)."/admin/federation/", t('Federation Statistics'), "federation"), //'update' => Array($a->get_baseurl(true)."/admin/update/", t("Software Update") , "update") ); @@ -150,7 +152,8 @@ function admin_content(&$a) { $t = get_markup_template("admin_aside.tpl"); $a->page['aside'] .= replace_macros( $t, array( - '$admin' => $aside, + '$admin' => $aside, + '$subpages' => $asidesubpages, '$admtxt' => t('Admin'), '$plugadmtxt' => t('Plugin Features'), '$logtxt' => t('Logs'), @@ -192,6 +195,9 @@ function admin_content(&$a) { case 'queue': $o = admin_page_queue($a); break; + case 'federation': + $o = admin_page_federation($a); + break; default: notice( t("Item not found.") ); } @@ -208,6 +214,47 @@ function admin_content(&$a) { } } +/** + * Admin Federation Stats Page; display some numbers from gserver + * @param App $a + * returning string + */ +function admin_page_federation(&$a) { + // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu + // social and statusnet nodes this node is knowing + // + // We are looking for the following platforms in the DB, "Red" should find + // all variants of that platform ID string as the q() function is stripping + // off one % two of them are needed in the query + $platforms = array('Diaspora', 'Friendica', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet'); + $counts = array(); + foreach ($platforms as $p) { + // get a totaö count for the platform, the name and version of the + // highest version and the protocol tpe + $c = q('select count(*), platform, network, version from gserver where platform like "'.$p.'" and last_contact > last_failure order by version asc;'); + // what versions for that platform do we know at all? + // again only the active nodes + $v = q('select count(*), version from gserver where last_contact > last_failure and platform like "'.$p.'" group by version order by version;'); + // the 3rd array item is needed for the JavaScript graphs as JS does + // not like some characters in the names of variables... + $counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p)); + } + // some helpful text + $intro = t('This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of.'); + $hint = t('The Auto Discovered Contact Directory feature is not enabled, it will improve the data displayed here.'); + // load the template, replace the macros and return the page content + $t = get_markup_template("admin_federation.tpl"); + return replace_macros($t, array( + '$title' => t('Administration'), + '$page' => t('Federation Statistics'), + '$intro' => $intro, + '$hint' => $hint, + '$autoactive' => get_config('system', 'poco_completion'), + '$counts' => $counts, + '$version' => FRIENDICA_VERSION, + '$legendtext' => t('Currently this node is aware of nodes from the following platforms:'), + )); +} /** * Admin Inspect Queue Page * @param App $a diff --git a/view/global.css b/view/global.css index f468633e7..ce69e2e27 100644 --- a/view/global.css +++ b/view/global.css @@ -276,9 +276,15 @@ a { #poke-recip-label, #poke-action-label, #prvmail-message-label { margin: 10px 0 10px; } +.version-match { + font-weight: bold; + color: #00a700; +} +ul.federation-stats, ul.credits { list-style: none; } +ul.federation-stats li, ul.credits li { float: left; width: 240px; diff --git a/view/templates/admin_aside.tpl b/view/templates/admin_aside.tpl index 4a6af8814..7753ce915 100644 --- a/view/templates/admin_aside.tpl +++ b/view/templates/admin_aside.tpl @@ -10,14 +10,12 @@ }); }); +

{{$admtxt}}

{{if $admin.update}} diff --git a/view/templates/admin_federation.tpl b/view/templates/admin_federation.tpl new file mode 100644 index 000000000..1fe8d2710 --- /dev/null +++ b/view/templates/admin_federation.tpl @@ -0,0 +1,60 @@ + + +
+

{{$title}} - {{$page}}

+

{{$intro}}

+ {{if not $autoactive}} +

{{$hint}}

+ {{/if}} +

{{$legendtext}} +

+

+
+ + + +{{foreach $counts as $c}} + + + + + + + +{{/foreach}} +
{{$c[0]['platform']}}{{$c[0]['count(*)']}} + {{$c[0]['network']}}
+ + +
    +{{foreach $c[1] as $v}} +
  • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['count(*)']}})
  • +{{/foreach}} +
+
From 4af584cec22827aee495e9d6bdd7366306254b06 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Thu, 26 Nov 2015 10:22:00 +0100 Subject: [PATCH 02/24] small fix for the ShaShape font --- view/fonts/shashape.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/fonts/shashape.css b/view/fonts/shashape.css index b34cac798..5f4494dde 100644 --- a/view/fonts/shashape.css +++ b/view/fonts/shashape.css @@ -177,7 +177,7 @@ content: "Z"; } .shashape.hash:before{ - content: "/"; + content: "#"; } .shashape.tag:before{ content: "="; From 25bb977b870feebed0c0bf759d9b82e3eac3b785 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 30 Nov 2015 07:43:45 +0100 Subject: [PATCH 03/24] better names for some variable to reflect their intention --- mod/admin.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 886d7a4d9..5e9c705ea 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -121,10 +121,10 @@ function admin_content(&$a) { /** * Side bar links */ - $aside = Array(); + $aside_tools = Array(); // array( url, name, extra css classes ) // not part of $aside to make the template more adjustable - $asidesubpages = Array( + $aside_sub = Array( 'site' => Array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"), 'users' => Array($a->get_baseurl(true)."/admin/users/", t("Users") , "users"), 'plugins'=> Array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"), @@ -138,7 +138,7 @@ function admin_content(&$a) { /* get plugins admin page */ $r = q("SELECT `name` FROM `addon` WHERE `plugin_admin`=1 ORDER BY `name`"); - $aside['plugins_admin']=Array(); + $aside_tools['plugins_admin']=Array(); foreach ($r as $h){ $plugin =$h['name']; $aside['plugins_admin'][] = Array($a->get_baseurl(true)."/admin/plugins/".$plugin, $plugin, "plugin"); @@ -146,14 +146,14 @@ function admin_content(&$a) { $a->plugins_admin[] = $plugin; } - $aside['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs"); - $aside['diagnostics_probe'] = Array($a->get_baseurl(true).'/probe/', t('probe address'), 'probe'); - $aside['diagnostics_webfinger'] = Array($a->get_baseurl(true).'/webfinger/', t('check webfinger'), 'webfinger'); + $aside_tools['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs"); + $aside_tools['diagnostics_probe'] = Array($a->get_baseurl(true).'/probe/', t('probe address'), 'probe'); + $aside_tools['diagnostics_webfinger'] = Array($a->get_baseurl(true).'/webfinger/', t('check webfinger'), 'webfinger'); $t = get_markup_template("admin_aside.tpl"); $a->page['aside'] .= replace_macros( $t, array( - '$admin' => $aside, - '$subpages' => $asidesubpages, + '$admin' => $aside_tools, + '$subpages' => $aside_sub, '$admtxt' => t('Admin'), '$plugadmtxt' => t('Plugin Features'), '$logtxt' => t('Logs'), From ce399928759320a29d9bfe47e60e607fe88408d9 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Tue, 1 Dec 2015 08:47:57 +0100 Subject: [PATCH 04/24] combine some versions for ~f and D* --- mod/admin.php | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 5e9c705ea..39677fb38 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -229,12 +229,69 @@ function admin_page_federation(&$a) { $platforms = array('Diaspora', 'Friendica', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet'); $counts = array(); foreach ($platforms as $p) { - // get a totaö count for the platform, the name and version of the + // get a total count for the platform, the name and version of the // highest version and the protocol tpe - $c = q('select count(*), platform, network, version from gserver where platform like "'.$p.'" and last_contact > last_failure order by version asc;'); + $c = q('select count(*), platform, network, version from gserver + where platform like "'.$p.'" and last_contact > last_failure + order by version asc;'); // what versions for that platform do we know at all? // again only the active nodes - $v = q('select count(*), version from gserver where last_contact > last_failure and platform like "'.$p.'" group by version order by version;'); + $v = q('select count(*), version from gserver + where last_contact > last_failure and platform like "'.$p.'" + group by version + order by version;'); + // + // clean up version numbers + // + // in the DB the Diaspora versions have the format x.x.x.x-xx the last + // part (-xx) should be removed to clean up the versions from the "head + // commit" information and combined into a single entry for x.x.x.x + if ($p=='Diaspora') { + $newV = array(); + $newVv = array(); + foreach($v as $vv) { + $newVC = $vv['count(*)']; + $newVV = $vv['version']; + $posDash = strpos($newVV, '-'); + if ($posDash) + $newVV = substr($newVV, 0, $posDash); + if (isset($newV[$newVV])) + { + $newV[$newVV] += $newVC; + } else { + $newV[$newVV] = $newVC; + } + } + foreach ($newV as $key => $value) { + array_push($newVv, array('count(*)'=>$value, 'version'=>$key)); + } + $v = $newVv; + } + // early friendica versions have the format x.x.xxxx where xxxx is the + // DB version stamp; those should be operated out and versions be + // conbined + if ($p=='Friendica') { + $newV = array(); + $newVv = array(); + foreach ($v as $vv) { + $newVC = $vv['count(*)']; + $newVV = $vv['version']; + $lastDot = strrpos($newVV,'.'); + $len = strlen($newVV)-1; + if ($lastDot == $len-4) + $newVV = substr($newVV, 0, $lastDot); + if (isset($newV[$newVV])) + { + $newV[$newVV] += $newVC; + } else { + $newV[$newVV] = $newVC; + } + } + foreach ($newV as $key => $value) { + array_push($newVv, array('count(*)'=>$value, 'version'=>$key)); + } + $v = $newVv; + } // the 3rd array item is needed for the JavaScript graphs as JS does // not like some characters in the names of variables... $counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p)); From 0905f18c0f2cbace91dd95a839e573ac89c1ad3c Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Wed, 9 Dec 2015 20:48:43 +0100 Subject: [PATCH 05/24] allow -rc in friendica version listings --- mod/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/admin.php b/mod/admin.php index 39677fb38..772d186ed 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -278,7 +278,7 @@ function admin_page_federation(&$a) { $newVV = $vv['version']; $lastDot = strrpos($newVV,'.'); $len = strlen($newVV)-1; - if ($lastDot == $len-4) + if (($lastDot == $len-4) && (!strrpos($newVV,'-rc')==$len-3)) $newVV = substr($newVV, 0, $lastDot); if (isset($newV[$newVV])) { From 8b189aca9ec45ad2c42e7a47ac7c78eaa5a7d91b Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 26 Dec 2015 08:49:38 +0100 Subject: [PATCH 06/24] some doxygen stuff --- mod/admin.php | 53 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 772d186ed..8add5d7f0 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -7,9 +7,18 @@ require_once("include/remoteupdate.php"); require_once("include/enotify.php"); require_once("include/text.php"); - /** + * @brief process send data from the admin panels subpages + * + * This function acts as relais for processing the data send from the subpages + * of the admin panel. Depending on the 1st parameter of the url (argv[1]) + * specialized functions are called to process the data from the subpages. + * + * The function itself does not return anything, but the subsequencely function + * return the HTML for the pages of the admin panel. + * * @param App $a + * */ function admin_post(&$a){ @@ -100,6 +109,8 @@ function admin_post(&$a){ } /** + * This function generates the content for the admin panel. + * @brief generates content of the admin panel pages * @param App $a * @return string */ @@ -215,9 +226,17 @@ function admin_content(&$a) { } /** - * Admin Federation Stats Page; display some numbers from gserver + * This function generates the "Federation Statistics" subpage for the admin + * panel. The page lists some numbers to the part of "The Federation" known to + * the node. This data includes the different connected networks (e.g. + * Diaspora, Hubzilla, GNU Social) and the used versions in the different + * networks. + * + * The returned string contains the HTML code of the subpage for display. + * + * @brief subpage with some stats about "the federstion" network * @param App $a - * returning string + * @return string */ function admin_page_federation(&$a) { // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu @@ -313,9 +332,9 @@ function admin_page_federation(&$a) { )); } /** - * Admin Inspect Queue Page + * @brief Admin Inspect Queue Page * @param App $a - * return string + * @return string */ function admin_page_queue(&$a) { // get content from the queue table @@ -337,7 +356,7 @@ function admin_page_queue(&$a) { )); } /** - * Admin Summary Page + * @brief Admin Summary Page * @param App $a * @return string */ @@ -390,8 +409,8 @@ function admin_page_summary(&$a) { /** - * Admin Site Page - * @param App $a + * @brief process send data from Admin Site Page + * @param App $a */ function admin_page_site_post(&$a){ if (!x($_POST,"page_site")){ @@ -705,6 +724,7 @@ function admin_page_site_post(&$a){ } /** + * @brief generate Admin Site subpage * @param App $a * @return string */ @@ -915,7 +935,11 @@ function admin_page_site(&$a) { } - +/** + * @brief generates admin panel subpage for DB syncronization + * @param App $a + * @return string + **/ function admin_page_dbsync(&$a) { $o = ''; @@ -995,8 +1019,7 @@ function admin_page_dbsync(&$a) { } /** - * Users admin page - * + * @brief process data send by Users admin page * @param App $a */ function admin_page_users_post(&$a){ @@ -1091,6 +1114,7 @@ function admin_page_users_post(&$a){ } /** + * @brief admin panel subpage for User management * @param App $a * @return string */ @@ -1251,8 +1275,7 @@ function admin_page_users(&$a){ /** - * Plugins admin page - * + * @brief Plugins admin page * @param App $a * @return string */ @@ -1624,8 +1647,7 @@ function admin_page_themes(&$a){ /** - * Logs admin page - * + * @brief prosesses data send by Logs admin page * @param App $a */ @@ -1650,6 +1672,7 @@ function admin_page_logs_post(&$a) { } /** + * @brief generates admin panel subpage for Logs * @param App $a * @return string */ From c1aa668fef4335f7694f696bd8f8d3ebd6b42d23 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 07:28:04 +0100 Subject: [PATCH 07/24] add log viewer to the aside menu of the admin panel --- view/templates/admin_aside.tpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/view/templates/admin_aside.tpl b/view/templates/admin_aside.tpl index 7753ce915..9291477af 100644 --- a/view/templates/admin_aside.tpl +++ b/view/templates/admin_aside.tpl @@ -37,6 +37,8 @@

{{$logtxt}}

{{$diagnosticstxt}}

From ddb17d36a2791cf6ec3c66d5bd8276982663f182 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 08:21:14 +0100 Subject: [PATCH 08/24] added PHP logging hint fields to the template --- view/templates/admin_logs.tpl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/view/templates/admin_logs.tpl b/view/templates/admin_logs.tpl index 4cc0acb66..e79c7d7af 100644 --- a/view/templates/admin_logs.tpl +++ b/view/templates/admin_logs.tpl @@ -1,19 +1,21 @@
-

{{$title}} - {{$page}}

+

{{$title}} - {{$page}}

- + - {{include file="field_checkbox.tpl" field=$debugging}} - {{include file="field_input.tpl" field=$logfile}} - {{include file="field_select.tpl" field=$loglevel}} + {{include file="field_checkbox.tpl" field=$debugging}} + {{include file="field_input.tpl" field=$logfile}} + {{include file="field_select.tpl" field=$loglevel}} -
+
+ +

{{$phpheader}}

+
+

{{$phphint}}

+
{{$phplogcode}}
+
-

{{$logname}}

-
{{$data}}
- -
From 0a5c9e96a884cce4bcae6ced5d5572c19224f74c Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 08:22:30 +0100 Subject: [PATCH 09/24] moved viewing of friendica logs into a separate subpage, thus created a new template --- view/templates/admin_viewlogs.tpl | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 view/templates/admin_viewlogs.tpl diff --git a/view/templates/admin_viewlogs.tpl b/view/templates/admin_viewlogs.tpl new file mode 100644 index 000000000..c80264c52 --- /dev/null +++ b/view/templates/admin_viewlogs.tpl @@ -0,0 +1,6 @@ +
+

{{$title}} - {{$page}}

+ +

{{$logname}}

+
{{$data}}
+
From 4d1545a1a924e82b73d894c715376ef55004a5b7 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 08:23:26 +0100 Subject: [PATCH 10/24] viewing and configuration of logs are now on separate subpages in the admin panel --- mod/admin.php | 93 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 10 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 8add5d7f0..c54b0e9cb 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -158,6 +158,7 @@ function admin_content(&$a) { } $aside_tools['logs'] = Array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs"); + $aside_tools['viewlogs'] = Array($a->get_baseurl(true)."/admin/viewlogs/", t("View Logs"), 'viewlogs'); $aside_tools['diagnostics_probe'] = Array($a->get_baseurl(true).'/probe/', t('probe address'), 'probe'); $aside_tools['diagnostics_webfinger'] = Array($a->get_baseurl(true).'/webfinger/', t('check webfinger'), 'webfinger'); @@ -165,12 +166,12 @@ function admin_content(&$a) { $a->page['aside'] .= replace_macros( $t, array( '$admin' => $aside_tools, '$subpages' => $aside_sub, - '$admtxt' => t('Admin'), - '$plugadmtxt' => t('Plugin Features'), - '$logtxt' => t('Logs'), - '$diagnosticstxt' => t('diagnostics'), - '$h_pending' => t('User registrations waiting for confirmation'), - '$admurl'=> $a->get_baseurl(true)."/admin/" + '$admtxt' => t('Admin'), + '$plugadmtxt' => t('Plugin Features'), + '$logtxt' => t('Logs'), + '$diagnosticstxt' => t('diagnostics'), + '$h_pending' => t('User registrations waiting for confirmation'), + '$admurl'=> $a->get_baseurl(true)."/admin/" )); @@ -197,6 +198,9 @@ function admin_content(&$a) { case 'logs': $o = admin_page_logs($a); break; + case 'viewlogs': + $o = admin_page_viewlogs($a); + break; case 'dbsync': $o = admin_page_dbsync($a); break; @@ -1672,7 +1676,18 @@ function admin_page_logs_post(&$a) { } /** - * @brief generates admin panel subpage for Logs + * @brief generates admin panel subpage for configuration of the logs + * + * This function take the view/templates/admin_logs.tpl file and generates a + * page where admin can configure the logging of friendica. + * + * Displaying the log is separated from the log config as the logfile can get + * big depending on the settings and changing settings regarding the logs can + * thus waste bandwidth. + * + * The string returned contains the content of the template file with replaced + * macros. + * * @param App $a * @return string */ @@ -1688,7 +1703,7 @@ function admin_page_logs(&$a){ $t = get_markup_template("admin_logs.tpl"); - $f = get_config('system','logfile'); +/* $f = get_config('system','logfile'); $data = ''; @@ -1717,14 +1732,14 @@ readable."); } fclose($fp); } - } + }*/ return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Logs'), '$submit' => t('Save Settings'), '$clear' => t('Clear'), - '$data' => $data, +// '$data' => $data, '$baseurl' => $a->get_baseurl(true), '$logname' => get_config('system','logfile'), @@ -1734,9 +1749,67 @@ readable."); '$loglevel' => array('loglevel', t("Log level"), get_config('system','loglevel'), "", $log_choices), '$form_security_token' => get_form_security_token("admin_logs"), + '$phpheader' => t("PHP logging"), + '$phphint' => t("To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."), + '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", )); } +/** + * @brief generates admin panel subpage to view the Friendica log + * + * This function loads the template view/templates/admin_viewlogs.tpl to + * display the systemlog content. The filename for the systemlog of friendica + * is relative to the base directory and taken from the config entry 'logfile' + * in the 'system' category. + * + * Displaying the log is separated from the log config as the logfile can get + * big depending on the settings and changing settings regarding the logs can + * thus waste bandwidth. + * + * The string returned contains the content of the template file with replaced + * macros. + * + * @param App $a + * @return string + */ +function admin_page_viewlogs(&$a){ + $t = get_markup_template("admin_viewlogs.tpl"); + $f = get_config('system','logfile'); + $data = ''; + + if(!file_exists($f)) { + $data = t("Error trying to open $f log file.\r\n
Check to see if file $f exist and is readable."); + } + else { + $fp = fopen($f, 'r'); + if(!$fp) { + $data = t("Couldn't open $f log file.\r\n
Check to see if file $f is readable."); + } + else { + $fstat = fstat($fp); + $size = $fstat['size']; + if($size != 0) + { + if($size > 5000000 || $size < 0) + $size = 5000000; + $seek = fseek($fp,0-$size,SEEK_END); + if($seek === 0) { + $data = escape_tags(fread($fp,$size)); + while(! feof($fp)) + $data .= escape_tags(fread($fp,4096)); + } + } + fclose($fp); + } + } + return replace_macros($t, array( + '$title' => t('Administration'), + '$page' => t('View Logs'), + '$data' => $data, + '$logname' => get_config('system','logfile') + )); +} /** * @param App $a */ From 0d5fed5b3bfba169f98742a7de4188bea7a31e76 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 08:27:53 +0100 Subject: [PATCH 11/24] beautification of HTML code --- view/templates/admin_aside.tpl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/view/templates/admin_aside.tpl b/view/templates/admin_aside.tpl index 9291477af..5c9cce0d0 100644 --- a/view/templates/admin_aside.tpl +++ b/view/templates/admin_aside.tpl @@ -37,8 +37,7 @@

{{$logtxt}}

{{$diagnosticstxt}}

From 1030c5f4b63df897c4cc96880063fc6ff0e56cb6 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 27 Dec 2015 16:03:42 +0100 Subject: [PATCH 12/24] some doc texts --- mod/admin.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index c54b0e9cb..616e8fcd4 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -337,6 +337,14 @@ function admin_page_federation(&$a) { } /** * @brief Admin Inspect Queue Page + * + * Generates a page for the admin to have a look into the current queue of + * postings that are not deliverabke. Shown are the name and url of the + * recipient, the delivery network and the dates when the posting was generated + * and the last time tried to deliver the posting. + * + * The returned string holds the content of the page. + * * @param App $a * @return string */ @@ -361,6 +369,12 @@ function admin_page_queue(&$a) { } /** * @brief Admin Summary Page + * + * The summary page is the "start page" of the admin panel. It gives the admin + * a first overview of the open adminastrative tasks. + * + * The returned string contains the HTML content of the generated page. + * * @param App $a * @return string */ @@ -1660,14 +1674,12 @@ function admin_page_logs_post(&$a) { check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); $logfile = ((x($_POST,'logfile')) ? notags(trim($_POST['logfile'])) : ''); - $debugging = ((x($_POST,'debugging')) ? true : false); + $debugging = ((x($_POST,'debugging')) ? true : false); $loglevel = ((x($_POST,'loglevel')) ? intval(trim($_POST['loglevel'])) : 0); set_config('system','logfile', $logfile); set_config('system','debugging', $debugging); set_config('system','loglevel', $loglevel); - - } info( t("Log settings updated.") ); From 8e7d53cd417951f855cd9aae51bd9993e5b969e0 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 4 Jan 2016 08:19:32 +0100 Subject: [PATCH 13/24] added Chart.js 1.0.2 to friendica library and use it instead of CDN version for graphs --- library/Chart.js-1.0.2/Chart.min.js | 11 +++++++++++ library/Chart.js-1.0.2/LICENSE.md | 7 +++++++ library/Chart.js-1.0.2/README.md | 20 ++++++++++++++++++++ view/templates/admin_federation.tpl | 2 +- 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 library/Chart.js-1.0.2/Chart.min.js create mode 100644 library/Chart.js-1.0.2/LICENSE.md create mode 100644 library/Chart.js-1.0.2/README.md diff --git a/library/Chart.js-1.0.2/Chart.min.js b/library/Chart.js-1.0.2/Chart.min.js new file mode 100644 index 000000000..3a0a2c873 --- /dev/null +++ b/library/Chart.js-1.0.2/Chart.min.js @@ -0,0 +1,11 @@ +/*! + * Chart.js + * http://chartjs.org/ + * Version: 1.0.2 + * + * Copyright 2015 Nick Downie + * Released under the MIT license + * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md + */ +(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;var i=function(t,i){return t["offset"+i]?t["offset"+i]:document.defaultView.getComputedStyle(t).getPropertyValue(i)},e=this.width=i(t.canvas,"Width"),n=this.height=i(t.canvas,"Height");t.canvas.width=e,t.canvas.height=n;var e=this.width=t.canvas.width,n=this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,customTooltips:!1,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof define&&define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),S=s.radians=function(t){return t*(Math.PI/180)},x=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),S=Math.round(f/v);(S>a||a>2*S)&&!h;)if(S>a)v*=2,S=Math.round(f/v),S%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,S=Math.round(f/v)}else v/=2,S=Math.round(f/v);return h&&(S=o,v=f/S),{steps:S,stepValue:v,min:p,max:p+S*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),w=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),st?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-w.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*w.easeInBounce(2*t):.5*w.easeOutBounce(2*t-1)+.5}}),b=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),L=(s.animationLoop=function(t,i,e,s,n,o){var a=0,h=w[e]||w.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=b(l):n.apply(o)};b(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),k=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},F=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},L(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){k(t.chart.canvas,e,i)})}),R=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},T=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),M=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},W=s.fontString=function(t,i,e){return i+" "+t+"px "+e},z=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},B=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return M(this.chart),this},stop:function(){return P(this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=R(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:T(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),F(this,this.events);var t=this.chart.canvas;t.width=this.chart.width,t.height=this.chart.height,t.style.removeProperty?(t.style.removeProperty("width"),t.style.removeProperty("height")):(t.style.removeAttribute("width"),t.style.removeAttribute("height")),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),this.options.customTooltips&&this.options.customTooltips(!1),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx,custom:this.options.customTooltips}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart,custom:this.options.customTooltips}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=this.caretPadding=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;if(t.fillStyle=this.fillColor,this.custom)this.custom(this);else{switch(this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}B(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=W(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=W(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=z(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){if(this.custom)this.custom(this);else{B(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?z(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),tthis.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=z(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(S(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(S(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/Math.max(this.valuesCount-(this.offsetGridLines?0:1),1),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a),l=this.showHorizontalLines;t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),0!==o||l||(l=!0),l&&t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),l&&(t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+x(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+x(this.lineWidth),o=this.xLabelRotation>0,a=this.showVerticalLines;0!==e||a||(a=!0),a&&t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),a&&(t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath()),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*S(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;ip&&(p=t.x+s,n=i),t.x-sp&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=W(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,scaleShowHorizontalLines:!0,scaleShowVerticalLines:!0,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<% for (var i=0; i
  • <%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(Math.abs(t)/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=Math.abs(t.value)},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)0&&ithis.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.ythis.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'
      <% for (var i=0; i
    • <%if(segments[i].label){%><%=segments[i].label%><%}%>
    • <%}%>
    '};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this); \ No newline at end of file diff --git a/library/Chart.js-1.0.2/LICENSE.md b/library/Chart.js-1.0.2/LICENSE.md new file mode 100644 index 000000000..e10bc0ff1 --- /dev/null +++ b/library/Chart.js-1.0.2/LICENSE.md @@ -0,0 +1,7 @@ +Copyright (c) 2013-2015 Nick Downie + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/library/Chart.js-1.0.2/README.md b/library/Chart.js-1.0.2/README.md new file mode 100644 index 000000000..7c4fa8bf6 --- /dev/null +++ b/library/Chart.js-1.0.2/README.md @@ -0,0 +1,20 @@ +# Chart.js + +[![Build Status](https://travis-ci.org/nnnick/Chart.js.svg?branch=master)](https://travis-ci.org/nnnick/Chart.js) [![Code Climate](https://codeclimate.com/github/nnnick/Chart.js/badges/gpa.svg)](https://codeclimate.com/github/nnnick/Chart.js) + + +*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org) + +## Documentation + +You can find documentation at [chartjs.org/docs](http://www.chartjs.org/docs/). The markdown files that build the site are available under `/docs`. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard. + +## Bugs, issues and contributing + +Before submitting an issue or a pull request to the project, please take a moment to look over the [contributing guidelines](https://github.com/nnnick/Chart.js/blob/master/CONTRIBUTING.md) first. + +For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/chartjs). + +## License + +Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT). diff --git a/view/templates/admin_federation.tpl b/view/templates/admin_federation.tpl index 1fe8d2710..2cc12ad0a 100644 --- a/view/templates/admin_federation.tpl +++ b/view/templates/admin_federation.tpl @@ -1,4 +1,4 @@ - +

    {{$title}} - {{$page}}

    From 5099f43c423909e257f601186b0f6697f9d4a928 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 4 Jan 2016 09:54:12 +0100 Subject: [PATCH 14/24] only show platforms with counts > 0 --- view/templates/admin_federation.tpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/view/templates/admin_federation.tpl b/view/templates/admin_federation.tpl index 2cc12ad0a..cd452c666 100644 --- a/view/templates/admin_federation.tpl +++ b/view/templates/admin_federation.tpl @@ -9,7 +9,9 @@

    {{$legendtext}}

      {{foreach $counts as $c}} + {{if $c[0]['count(*)'] > 0}}
    • {{$c[0]['platform']}} ({{$c[0]['count(*)']}})
    • + {{/if}} {{/foreach}}

    @@ -30,6 +32,7 @@ document.getElementById('FederationLegend').innerHTML = myDoughnutChart.generate {{foreach $counts as $c}} +{{if $c[0]['count(*)'] > 0}} +{{/if}} {{/foreach}}
    {{$c[0]['platform']}} {{$c[0]['count(*)']}} @@ -56,5 +59,6 @@ var my{{$c[2]}}DoughnutChart = new Chart(ctx).Doughnut({{$c[2]}}data,
    From e3fd0a269b8ab29c2af2fb84a2714d92ee50681d Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 4 Jan 2016 09:55:30 +0100 Subject: [PATCH 15/24] some doc strings, sort platforms for federation stats page --- mod/admin.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 616e8fcd4..34e9b5c03 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -238,7 +238,7 @@ function admin_content(&$a) { * * The returned string contains the HTML code of the subpage for display. * - * @brief subpage with some stats about "the federstion" network + * @brief subpage with some stats about "the federation" network * @param App $a * @return string */ @@ -249,7 +249,9 @@ function admin_page_federation(&$a) { // We are looking for the following platforms in the DB, "Red" should find // all variants of that platform ID string as the q() function is stripping // off one % two of them are needed in the query - $platforms = array('Diaspora', 'Friendica', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet'); + // Add more platforms if you like, when one returns 0 known nodes it is not + // displayed on the stats page. + $platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet'); $counts = array(); foreach ($platforms as $p) { // get a total count for the platform, the name and version of the @@ -333,6 +335,7 @@ function admin_page_federation(&$a) { '$counts' => $counts, '$version' => FRIENDICA_VERSION, '$legendtext' => t('Currently this node is aware of nodes from the following platforms:'), + '$baseurl' => $a->get_baseurl(), )); } /** @@ -743,6 +746,9 @@ function admin_page_site_post(&$a){ /** * @brief generate Admin Site subpage + * + * This function generates the main configuration page of the admin panel. + * * @param App $a * @return string */ @@ -955,6 +961,13 @@ function admin_page_site(&$a) { /** * @brief generates admin panel subpage for DB syncronization + * + * This page checks if the database of friendica is in sync with the specs. + * Should this not be the case, it attemps to sync the structure and notifies + * the admin if the automatic process was failing. + * + * The returned string holds the HTML code of the page. + * * @param App $a * @return string **/ @@ -1133,6 +1146,13 @@ function admin_page_users_post(&$a){ /** * @brief admin panel subpage for User management + * + * This function generates the admin panel page for user management of the + * node. It offers functionality to add/block/delete users and offers some + * statistics about the userbase. + * + * The returned string holds the HTML code of the page. + * * @param App $a * @return string */ From 7a7ffb2299e6614c00545a35f3d1a844bed52982 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sun, 10 Jan 2016 13:04:07 +0100 Subject: [PATCH 16/24] issue 2240 when no addon are installed hint the location of sources in the admin panel --- mod/admin.php | 2 ++ view/templates/admin_plugins.tpl | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/mod/admin.php b/mod/admin.php index 34e9b5c03..16c3a23d4 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1441,6 +1441,8 @@ function admin_page_plugins(&$a){ '$baseurl' => $a->get_baseurl(true), '$function' => 'plugins', '$plugins' => $plugins, + '$pcount' => count($plugins), + '$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'), '$form_security_token' => get_form_security_token("admin_themes"), )); } diff --git a/view/templates/admin_plugins.tpl b/view/templates/admin_plugins.tpl index 6caa04a3a..fb1f26a90 100644 --- a/view/templates/admin_plugins.tpl +++ b/view/templates/admin_plugins.tpl @@ -2,6 +2,11 @@

    {{$title}} - {{$page}}

    {{$reload}} + {{if $pcount eq 0}} +
    + {{$noplugshint}} +
    + {{else}}
      {{foreach $plugins as $p}}
    • @@ -13,4 +18,5 @@
    • {{/foreach}}
    + {{/if}}
    From 629c69d9ddd27806d56cccac872c22d730360d4d Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Fri, 15 Jan 2016 19:35:45 +0100 Subject: [PATCH 17/24] only show the reload link if plugins are found --- view/templates/admin_plugins.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view/templates/admin_plugins.tpl b/view/templates/admin_plugins.tpl index fb1f26a90..75565dd2e 100644 --- a/view/templates/admin_plugins.tpl +++ b/view/templates/admin_plugins.tpl @@ -1,12 +1,12 @@

    {{$title}} - {{$page}}

    - {{$reload}} {{if $pcount eq 0}} -
    +
    {{$noplugshint}}
    {{else}} + {{$reload}}
      {{foreach $plugins as $p}}
    • From 11aa76c270e616862728107c0612767040e74d2a Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Fri, 15 Jan 2016 20:03:41 +0100 Subject: [PATCH 18/24] Theme listing works again, added some docs for theme and plugin listing funkctions --- mod/admin.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 16c3a23d4..a72eed9e3 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1314,6 +1314,15 @@ function admin_page_users(&$a){ /** * @brief Plugins admin page + * + * This function generates the admin panel page for managing plugins on the + * friendica node. + * + * The template used for displaying the list of plugins and the details of the + * plugin are the same as used for the templates. + * + * The returned string returned hulds the HTML code of the page. + * * @param App $a * @return string */ @@ -1507,7 +1516,15 @@ function rebuild_theme_table($themes) { /** - * Themes admin page + * @brief Themes admin page + * + * This function generates the admin panel page to control the themes available + * on the friendica node. + * + * The template used for displaying the list of themes and the details of the + * themes are the same as used for the plugins. + * + * The returned string contains the HTML code of the admin panel page. * * @param App $a * @return string @@ -1619,6 +1636,7 @@ function admin_page_themes(&$a){ if(! stristr($screenshot[0],$theme)) $screenshot = null; + $t = get_markup_template("admin_plugins_details.tpl"); return replace_macros($t, array( '$title' => t('Administration'), @@ -1626,7 +1644,6 @@ function admin_page_themes(&$a){ '$toggle' => t('Toggle'), '$settings' => t('Settings'), '$baseurl' => $a->get_baseurl(true), - '$plugin' => $theme, '$status' => $status, '$action' => $action, @@ -1679,6 +1696,8 @@ function admin_page_themes(&$a){ '$baseurl' => $a->get_baseurl(true), '$function' => 'themes', '$plugins' => $xthemes, + '$pcount' => count($themes), + '$noplugshint' => sprintf(t('No themes found on the system. They should be paced in %1$s'),'/view/themes'), '$experimental' => t('[Experimental]'), '$unsupported' => t('[Unsupported]'), '$form_security_token' => get_form_security_token("admin_themes"), From 954e4f2754e4e497a313d0b80ce528318df52731 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Fri, 15 Jan 2016 20:40:01 +0100 Subject: [PATCH 19/24] more docs --- mod/admin.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index a72eed9e3..f3fb56f60 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1316,7 +1316,9 @@ function admin_page_users(&$a){ * @brief Plugins admin page * * This function generates the admin panel page for managing plugins on the - * friendica node. + * friendica node. If a plugin name is given a single page showing the details + * for this addon is generated. If no name is given, a list of available + * plugins is shown. * * The template used for displaying the list of plugins and the details of the * plugin are the same as used for the templates. @@ -1519,7 +1521,9 @@ function rebuild_theme_table($themes) { * @brief Themes admin page * * This function generates the admin panel page to control the themes available - * on the friendica node. + * on the friendica node. If the name of a theme is given as parameter a page + * with the details for the theme is shown. Otherwise a list of available + * themes is generated. * * The template used for displaying the list of themes and the details of the * themes are the same as used for the plugins. From 20fe67f3782e6ad90fed64d70f752d6524d20157 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Jan 2016 11:52:21 +0100 Subject: [PATCH 20/24] removed remote update functionality from admin panel --- include/remoteupdate.php | 261 -------------------------- mod/admin.php | 59 ------ view/templates/admin_remoteupdate.tpl | 99 ---------- 3 files changed, 419 deletions(-) delete mode 100644 include/remoteupdate.php delete mode 100644 view/templates/admin_remoteupdate.tpl diff --git a/include/remoteupdate.php b/include/remoteupdate.php deleted file mode 100644 index 9effc9b6e..000000000 --- a/include/remoteupdate.php +++ /dev/null @@ -1,261 +0,0 @@ -tags as $i=>$v){ - $i = (float)$i; - if ($i>$tag) $tag=$i; - } - - if ($tag==0.0) return false; - $f = fetch_url("https://raw.github.com/".F9KREPO."/".$tag."/boot.php","r"); - preg_match("|'FRIENDICA_VERSION', *'([^']*)'|", $f, $m); - $version = $m[1]; - - $lv = explode(".", FRIENDICA_VERSION); - $rv = explode(".",$version); - foreach($lv as $i=>$v){ - if ((int)$lv[$i] < (int)$rv[$i]) { - return array($tag, $version, "https://github.com/friendica/friendica/zipball/".$tag); - break; - } - } - return false; -} -function canWeWrite(){ - $bd = dirname(dirname(__file__)); - return is_writable( $bd."/boot.php" ); -} - -function out($txt){ echo "§".$txt."§"; ob_end_flush(); flush();} - -function up_count($path){ - - $file_count = 0; - - $dir_handle = opendir($path); - - if (!$dir_handle) return -1; - - while ($file = readdir($dir_handle)) { - - if ($file == '.' || $file == '..') continue; - $file_count++; - - if (is_dir($path . $file)){ - $file_count += up_count($path . $file . DIRECTORY_SEPARATOR); - } - - } - - closedir($dir_handle); - - return $file_count; -} - - - -function up_unzip($file, $folder="/tmp"){ - $folder.="/"; - $zip = zip_open($file); - if ($zip) { - while ($zip_entry = zip_read($zip)) { - $zip_entry_name = zip_entry_name($zip_entry); - if (substr($zip_entry_name,strlen($zip_entry_name)-1,1)=="/"){ - mkdir($folder.$zip_entry_name,0777, true); - } else { - $fp = fopen($folder.$zip_entry_name, "w"); - if (zip_entry_open($zip, $zip_entry, "r")) { - $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); - fwrite($fp,"$buf"); - zip_entry_close($zip_entry); - fclose($fp); - } - } - } - zip_close($zip); - } -} - -/** - * Walk recoursively in a folder and call a callback function on every - * dir entry. - * args: - * $dir string base dir to walk - * $callback function callback function - * $sort int 0: ascending, 1: descending - * $cb_argv any extra value passed to callback - * - * callback signature: - * function name($fn, $dir [, $argv]) - * $fn string full dir entry name - * $dir string start dir path - * $argv any user value to callback - * - */ -function up_walktree($dir, $callback=Null, $sort=0, $cb_argv=Null , $startdir=Null){ - if (is_null($callback)) return; - if (is_null($startdir)) $startdir = $dir; - $res = scandir($dir, $sort); - foreach($res as $i=>$v){ - if ($v!="." && $v!=".."){ - $fn = $dir."/".$v; - if ($sort==0) $callback($fn, $startdir, $cb_argv); - if (is_dir($fn)) up_walktree($fn, $callback, $sort, $cb_argv, $startdir); - if ($sort==1) $callback($fn, $startdir, $cb_argv); - } - } - -} - -function up_copy($fn, $dir){ - global $up_countfiles, $up_totalfiles, $up_lastp; - $up_countfiles++; $prc=(int)(((float)$up_countfiles/(float)$up_totalfiles)*100); - - if (strpos($fn, ".gitignore")>-1 || strpos($fn, ".htaccess")>-1) return; - $ddest = dirname(dirname(__file__)); - $fd = str_replace($dir, $ddest, $fn); - - if (is_dir($fn) && !is_dir($fd)) { - $re=mkdir($fd,0777,true); - } - if (!is_dir($fn)){ - $re=copy($fn, $fd); - } - - if ($re===false) { - out("ERROR. Abort."); - killme(); - } - out("copy@Copy@$prc%"); -} - -function up_ftp($fn, $dir, $argv){ - global $up_countfiles, $up_totalfiles, $up_lastp; - $up_countfiles++; $prc=(int)(((float)$up_countfiles/(float)$up_totalfiles)*100); - - if (strpos($fn, ".gitignore")>-1 || strpos($fn, ".htaccess")>-1) return; - - list($ddest, $conn_id) = $argv; - $l = strlen($ddest)-1; - if (substr($ddest,$l,1)=="/") $ddest = substr($ddest,0,$l); - $fd = str_replace($dir, $ddest, $fn); - - if (is_dir($fn)){ - if (ftp_nlist($conn_id, $fd)===false) { - $ret = ftp_mkdir($conn_id, $fd); - } else { - $ret=true; - } - } else { - $ret = ftp_put($conn_id, $fd, $fn, FTP_BINARY); - } - if (!$ret) { - out("ERROR. Abort."); - killme(); - } - out("copy@Copy@$prc%"); -} - -function up_rm($fn, $dir){ - if (is_dir($fn)){ - rmdir($fn); - } else { - unlink($fn); - } -} - -function up_dlfile($url, $file) { - $in = fopen ($url, "r"); - $out = fopen ($file, "w"); - - $fs = filesize($url); - - - if (!$in || !$out) return false; - - $s=0; $count=0; - while (!feof ($in)) { - $line = fgets ($in, 1024); - fwrite( $out, $line); - - $count++; $s += strlen($line); - if ($count==50){ - $count=0; - $sp=$s/1024.0; $ex="Kb"; - if ($sp>1024) { $sp=$sp/1024; $ex="Mb"; } - if ($sp>1024) { $sp=$sp/1024; $ex="Gb"; } - $sp = ((int)($sp*100))/100; - out("dwl@Download@".$sp.$ex); - } - } - fclose($in); - return true; -} - -function doUpdate($remotefile, $ftpdata=false){ - global $up_totalfiles; - - - $localtmpfile = tempnam("/tmp", "fk"); - out("dwl@Download@starting..."); - $rt= up_dlfile($remotefile, $localtmpfile); - if ($rt==false || filesize($localtmpfile)==0){ - out("dwl@Download@ERROR."); - unlink($localtmpfile); - return; - } - out("dwl@Download@Ok."); - - out("unzip@Unzip@"); - $tmpdirname = $localfile."ex"; - mkdir($tmpdirname); - up_unzip($localtmpfile, $tmpdirname); - $basedir = glob($tmpdirname."/*"); $basedir=$basedir[0]; - out ("unzip@Unzip@Ok."); - - $up_totalfiles = up_count($basedir."/"); - - if (canWeWrite()){ - out("copy@Copy@"); - up_walktree($basedir, 'up_copy'); - } - if ($ftpdata!==false && is_array($ftpdata) && $ftpdata['ftphost']!="" ){ - out("ftpcon@Connect to FTP@"); - $conn_id = ftp_connect($ftpdata['ftphost']); - $login_result = ftp_login($conn_id, $ftpdata['ftpuser'], $ftpdata['ftppwd']); - - if ((!$conn_id) || (!$login_result)) { - out("ftpcon@Connect to FTP@FAILED"); - up_clean($tmpdirname, $localtmpfile); - return; - } else { - out("ftpcon@Connect to FTP@Ok."); - } - out("copy@Copy@"); - up_walktree($basedir, 'up_ftp', 0, array( $ftpdata['ftppath'], $conn_id)); - - ftp_close($conn_id); - } - - up_clean($tmpdirname, $localtmpfile); - -} - -function up_clean($tmpdirname, $localtmpfile){ - out("clean@Clean up@"); - unlink($localtmpfile); - up_walktree($tmpdirname, 'up_rm', 1); - rmdir($tmpdirname); - out("clean@Clean up@Ok."); -} diff --git a/mod/admin.php b/mod/admin.php index f3fb56f60..52367e8a2 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -3,7 +3,6 @@ /** * Friendica admin */ -require_once("include/remoteupdate.php"); require_once("include/enotify.php"); require_once("include/text.php"); @@ -1867,61 +1866,3 @@ function admin_page_viewlogs(&$a){ '$logname' => get_config('system','logfile') )); } -/** - * @param App $a - */ -function admin_page_remoteupdate_post(&$a) { - // this function should be called via ajax post - if(!is_site_admin()) { - return; - } - - - if (x($_POST,'remotefile') && $_POST['remotefile']!=""){ - $remotefile = $_POST['remotefile']; - $ftpdata = (x($_POST['ftphost'])?$_POST:false); - doUpdate($remotefile, $ftpdata); - } else { - echo "No remote file to download. Abort!"; - } - - killme(); -} - -/** - * @param App $a - * @return string - */ -function admin_page_remoteupdate(&$a) { - if(!is_site_admin()) { - return login(false); - } - - $canwrite = canWeWrite(); - $canftp = function_exists('ftp_connect'); - - $needupdate = true; - $u = checkUpdate(); - if (!is_array($u)){ - $needupdate = false; - $u = array('','',''); - } - - $tpl = get_markup_template("admin_remoteupdate.tpl"); - return replace_macros($tpl, array( - '$baseurl' => $a->get_baseurl(true), - '$submit' => t("Update now"), - '$close' => t("Close"), - '$localversion' => FRIENDICA_VERSION, - '$remoteversion' => $u[1], - '$needupdate' => $needupdate, - '$canwrite' => $canwrite, - '$canftp' => $canftp, - '$ftphost' => array('ftphost', t("FTP Host"), '',''), - '$ftppath' => array('ftppath', t("FTP Path"), '/',''), - '$ftpuser' => array('ftpuser', t("FTP User"), '',''), - '$ftppwd' => array('ftppwd', t("FTP Password"), '',''), - '$remotefile'=>array('remotefile','', $u['2'],''), - )); - -} diff --git a/view/templates/admin_remoteupdate.tpl b/view/templates/admin_remoteupdate.tpl deleted file mode 100644 index c3e85f2e8..000000000 --- a/view/templates/admin_remoteupdate.tpl +++ /dev/null @@ -1,99 +0,0 @@ - - - - -
      -
      Your version:
      {{$localversion}}
      -{{if $needupdate}} -
      New version:
      {{$remoteversion}}
      - -
      - - - {{if $canwrite}} -
      - {{else}} -

      Your friendica installation is not writable by web server.

      - {{if $canftp}} -

      You can try to update via FTP

      - {{include file="field_input.tpl" field=$ftphost}} - {{include file="field_input.tpl" field=$ftppath}} - {{include file="field_input.tpl" field=$ftpuser}} - {{include file="field_password.tpl" field=$ftppwd}} -
      - {{/if}} - {{/if}} -
      -{{else}} -

      No updates

      -{{/if}} -
      From 7f80de6db8af7a50b4d99ebdac1cf064e9b669c3 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Jan 2016 12:45:48 +0100 Subject: [PATCH 21/24] removed calls to the remote_update funcions --- mod/admin.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 52367e8a2..2c519729e 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -97,9 +97,6 @@ function admin_post(&$a){ case 'dbsync': admin_page_dbsync_post($a); break; - case 'update': - admin_page_remoteupdate_post($a); - break; } } @@ -142,7 +139,6 @@ function admin_content(&$a) { 'dbsync' => Array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"), 'queue' => Array($a->get_baseurl(true)."/admin/queue/", t('Inspect Queue'), "queue"), 'federation' => Array($a->get_baseurl(true)."/admin/federation/", t('Federation Statistics'), "federation"), - //'update' => Array($a->get_baseurl(true)."/admin/update/", t("Software Update") , "update") ); /* get plugins admin page */ @@ -203,9 +199,6 @@ function admin_content(&$a) { case 'dbsync': $o = admin_page_dbsync($a); break; - case 'update': - $o = admin_page_remoteupdate($a); - break; case 'queue': $o = admin_page_queue($a); break; From 8730c72156a9b605eac97a4ac4822529733a733d Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Jan 2016 13:45:21 +0100 Subject: [PATCH 22/24] removed commented out code, beautification of MySQL statements --- mod/admin.php | 54 +++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 2c519729e..a846ddb0e 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -248,15 +248,15 @@ function admin_page_federation(&$a) { foreach ($platforms as $p) { // get a total count for the platform, the name and version of the // highest version and the protocol tpe - $c = q('select count(*), platform, network, version from gserver - where platform like "'.$p.'" and last_contact > last_failure - order by version asc;'); + $c = q('SELECT count(*) AS total, platform, network, version FROM gserver + WHERE platform LIKE "%s" AND last_contact > last_failure + ORDER BY version ASC;', $p); // what versions for that platform do we know at all? // again only the active nodes - $v = q('select count(*), version from gserver - where last_contact > last_failure and platform like "'.$p.'" - group by version - order by version;'); + $v = q('SELECT count(*) AS total, version FROM gserver + WHERE last_contact > last_failure AND platform LIKE "%s" + GROUP BY version + ORDER BY version;', $p); // // clean up version numbers // @@ -267,7 +267,7 @@ function admin_page_federation(&$a) { $newV = array(); $newVv = array(); foreach($v as $vv) { - $newVC = $vv['count(*)']; + $newVC = $vv['total']; $newVV = $vv['version']; $posDash = strpos($newVV, '-'); if ($posDash) @@ -280,7 +280,7 @@ function admin_page_federation(&$a) { } } foreach ($newV as $key => $value) { - array_push($newVv, array('count(*)'=>$value, 'version'=>$key)); + array_push($newVv, array('total'=>$value, 'version'=>$key)); } $v = $newVv; } @@ -291,7 +291,7 @@ function admin_page_federation(&$a) { $newV = array(); $newVv = array(); foreach ($v as $vv) { - $newVC = $vv['count(*)']; + $newVC = $vv['total']; $newVV = $vv['version']; $lastDot = strrpos($newVV,'.'); $len = strlen($newVV)-1; @@ -305,7 +305,7 @@ function admin_page_federation(&$a) { } } foreach ($newV as $key => $value) { - array_push($newVv, array('count(*)'=>$value, 'version'=>$key)); + array_push($newVv, array('total'=>$value, 'version'=>$key)); } $v = $newVv; } @@ -1752,43 +1752,11 @@ function admin_page_logs(&$a){ $t = get_markup_template("admin_logs.tpl"); -/* $f = get_config('system','logfile'); - - $data = ''; - - if(!file_exists($f)) { - $data = t("Error trying to open $f log file.\r\n
      Check to see if file $f exist and is -readable."); - } - else { - $fp = fopen($f, 'r'); - if(!$fp) { - $data = t("Couldn't open $f log file.\r\n
      Check to see if file $f is readable."); - } - else { - $fstat = fstat($fp); - $size = $fstat['size']; - if($size != 0) - { - if($size > 5000000 || $size < 0) - $size = 5000000; - $seek = fseek($fp,0-$size,SEEK_END); - if($seek === 0) { - $data = escape_tags(fread($fp,$size)); - while(! feof($fp)) - $data .= escape_tags(fread($fp,4096)); - } - } - fclose($fp); - } - }*/ - return replace_macros($t, array( '$title' => t('Administration'), '$page' => t('Logs'), '$submit' => t('Save Settings'), '$clear' => t('Clear'), -// '$data' => $data, '$baseurl' => $a->get_baseurl(true), '$logname' => get_config('system','logfile'), From 75f005355077eda510e7446bddababa5dc06b347 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Jan 2016 13:57:40 +0100 Subject: [PATCH 23/24] forgot the template --- view/templates/admin_federation.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/view/templates/admin_federation.tpl b/view/templates/admin_federation.tpl index cd452c666..b1c56cd07 100644 --- a/view/templates/admin_federation.tpl +++ b/view/templates/admin_federation.tpl @@ -9,8 +9,8 @@

      {{$legendtext}}

        {{foreach $counts as $c}} - {{if $c[0]['count(*)'] > 0}} -
      • {{$c[0]['platform']}} ({{$c[0]['count(*)']}})
      • + {{if $c[0]['total'] > 0}} +
      • {{$c[0]['platform']}} ({{$c[0]['total']}})
      • {{/if}} {{/foreach}}
      @@ -19,7 +19,7 @@
        {{foreach $c[1] as $v}} -
      • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['count(*)']}})
      • +
      • {{if ($c[0]['platform']==='Friendica' and $version===$v['version']) }}{{$v['version']}}{{else}}{{$v['version']}}{{/if}} ({{$v['total']}})
      • {{/foreach}}
      From 1770267934a71e30a5dc288711e64af7045718c9 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 16 Jan 2016 14:12:55 +0100 Subject: [PATCH 24/24] move @brief to the top of the doc block --- mod/admin.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index a846ddb0e..a035b746a 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -105,8 +105,10 @@ function admin_post(&$a){ } /** - * This function generates the content for the admin panel. * @brief generates content of the admin panel pages + * + * This function generates the content for the admin panel. + * * @param App $a * @return string */ @@ -222,6 +224,8 @@ function admin_content(&$a) { } /** + * @brief subpage with some stats about "the federation" network + * * This function generates the "Federation Statistics" subpage for the admin * panel. The page lists some numbers to the part of "The Federation" known to * the node. This data includes the different connected networks (e.g. @@ -230,7 +234,6 @@ function admin_content(&$a) { * * The returned string contains the HTML code of the subpage for display. * - * @brief subpage with some stats about "the federation" network * @param App $a * @return string */