public function ajax()
 {
     $apiArgs = isset($_GET["apiArgs"]) ? $_GET["apiArgs"] : array();
     if (!$apiArgs) {
         wp_send_json_error(array("error" => "MISSING_APIARGS"));
         exit;
     }
     if (empty($apiArgs["since_id"]) || !is_numeric($apiArgs["since_id"])) {
         wp_send_json_error(array("error" => "MISSING_SINCE_ID"));
         exit;
     }
     // $since_id = isset( $_GET["since_id"] ) ? absint($_GET["since_id"]) : null;
     $logQueryArgs = $apiArgs;
     $logQuery = new SimpleHistoryLogQuery();
     $answer = $logQuery->query($logQueryArgs);
     // Use our own repsonse array instead of $answer to keep size down
     $json_data = array();
     $numNewRows = isset($answer["total_row_count"]) ? $answer["total_row_count"] : 0;
     $json_data["num_new_rows"] = $numNewRows;
     $json_data["num_mysql_queries"] = get_num_queries();
     if ($numNewRows) {
         // We have new rows
         // Append strings
         $textRowsFound = sprintf(_n('1 new event', '%d new events', $numNewRows, 'simple-history'), $numNewRows);
         $json_data["strings"] = array("newRowsFound" => $textRowsFound);
     }
     wp_send_json_success($json_data);
 }
Esempio n. 2
0
    /**
     * Quick stats above the log
     * Uses filter "simple_history/history_page/before_gui" to output its contents
     */
    public function output_quick_stats()
    {
        global $wpdb;
        // Get number of events today
        $logQuery = new SimpleHistoryLogQuery();
        $logResults = $logQuery->query(array("posts_per_page" => 1, "date_from" => strtotime("today")));
        $total_row_count = (int) $logResults["total_row_count"];
        // Get sql query for where to read only loggers current user is allowed to read/view
        $sql_loggers_in = $this->getLoggersThatUserCanRead(get_current_user_id(), "sql");
        // Get number of users today, i.e. events with wp_user as initiator
        $sql_users_today = sprintf('
			SELECT
				DISTINCT(c.value) AS user_id
				#h.id, h.logger, h.level, h.initiator, h.date
				FROM %3$s AS h
			INNER JOIN %4$s AS c
			ON c.history_id = h.id AND c.key = "_user_id"
			WHERE
				initiator = "wp_user"
				AND logger IN %1$s
				AND date > "%2$s"
			', $sql_loggers_in, date("Y-m-d H:i", strtotime("today")), $wpdb->prefix . SimpleHistory::DBTABLE, $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS);
        $cache_key = "quick_stats_users_today_" . md5(serialize($sql_loggers_in));
        $cache_group = "simple-history-" . $this->get_cache_incrementor();
        $results_users_today = wp_cache_get($cache_key, $cache_group);
        if (false === $results_users_today) {
            $results_users_today = $wpdb->get_results($sql_users_today);
            wp_cache_set($cache_key, $results_users_today, $cache_group);
        }
        $count_users_today = sizeof($results_users_today);
        // Get number of other sources (not wp_user)
        $sql_other_sources_where = sprintf('
				initiator <> "wp_user"
				AND logger IN %1$s
				AND date > "%2$s"
			', $sql_loggers_in, date("Y-m-d H:i", strtotime("today")), $wpdb->prefix . SimpleHistory::DBTABLE, $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS);
        $sql_other_sources_where = apply_filters("simple_history/quick_stats_where", $sql_other_sources_where);
        $sql_other_sources = sprintf('
			SELECT
				DISTINCT(h.initiator) AS initiator
			FROM %3$s AS h
			WHERE
				%5$s
			', $sql_loggers_in, date("Y-m-d H:i", strtotime("today")), $wpdb->prefix . SimpleHistory::DBTABLE, $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS, $sql_other_sources_where);
        // sf_d($sql_other_sources, '$sql_other_sources');
        $cache_key = "quick_stats_results_other_sources_today_" . md5(serialize($sql_other_sources));
        $results_other_sources_today = wp_cache_get($cache_key, $cache_group);
        if (false === $results_other_sources_today) {
            $results_other_sources_today = $wpdb->get_results($sql_other_sources);
            wp_cache_set($cache_key, $results_other_sources_today, $cache_group);
        }
        $count_other_sources = sizeof($results_other_sources_today);
        //sf_d($logResults, '$logResults');
        //sf_d($results_users_today, '$sql_users_today');
        //sf_d($results_other_sources_today, '$results_other_sources_today');
        ?>
		<div class="SimpleHistoryQuickStats">
			<p>
				<?php 
        $msg_tmpl = "";
        // No results today at all
        if ($total_row_count == 0) {
            $msg_tmpl = __("No events today so far.", "simple-history");
        } else {
            /*
            					Type of results
            					x1 event today from 1 user.
            					x1 event today from 1 source.
            					3 events today from 1 user.
            					x2 events today from 2 users.
            					x2 events today from 1 user and 1 other source.
            					x3 events today from 2 users and 1 other source.
            					x3 events today from 1 user and 2 other sources.
            					x4 events today from 2 users and 2 other sources.
            */
            // A single event existed and was from a user
            // 1 event today from 1 user.
            if ($total_row_count == 1 && $count_users_today == 1) {
                $msg_tmpl .= __('One event today from one user.', "simple-history");
            }
            // A single event existed and was from another source
            // 1 event today from 1 source.
            if ($total_row_count == 1 && !$count_users_today) {
                $msg_tmpl .= __('One event today from one source.', "simple-history");
            }
            // Multiple events from a single user
            // 3 events today from one user.
            if ($total_row_count > 1 && $count_users_today == 1 && !$count_other_sources) {
                $msg_tmpl .= __('%1$d events today from one user.', "simple-history");
            }
            // Multiple events from only users
            // 2 events today from 2 users.
            if ($total_row_count > 1 && $count_users_today == $total_row_count) {
                $msg_tmpl .= __('%1$d events today from %2$d users.', "simple-history");
            }
            // Multiple events from 1 single user and 1 single other source
            // 2 events today from 1 user and 1 other source.
            if ($total_row_count && 1 == $count_users_today && 1 == $count_other_sources) {
                $msg_tmpl .= __('%1$d events today from one user and one other source.', "simple-history");
            }
            // Multiple events from multple users but from only 1 single other source
            // 3 events today from 2 users and 1 other source.
            if ($total_row_count > 1 && $count_users_today > 1 && $count_other_sources == 1) {
                $msg_tmpl .= __('%1$d events today from one user and one other source.', "simple-history");
            }
            // Multiple events from 1 user but from multiple  other source
            // 3 events today from 1 user and 2 other sources.
            if ($total_row_count > 1 && 1 == $count_users_today && $count_other_sources > 1) {
                $msg_tmpl .= __('%1$d events today from one user and %3$d other sources.', "simple-history");
            }
            // Multiple events from multiple user and from multiple other sources
            // 4 events today from 2 users and 2 other sources.
            if ($total_row_count > 1 && $count_users_today > 1 && $count_other_sources > 1) {
                $msg_tmpl .= __('%1$s events today from %2$d users and %3$d other sources.', "simple-history");
            }
        }
        // only show stats if we have something to output
        if ($msg_tmpl) {
            printf($msg_tmpl, $logResults["total_row_count"], $count_users_today, $count_other_sources);
            // Space between texts
            /*
            				echo " ";
            
            				// http://playground-root.ep/wp-admin/options-general.php?page=simple_history_settings_menu_slug&selected-tab=stats
            				printf(
            				'<a href="%1$s">View more stats</a>.',
            				add_query_arg("selected-tab", "stats", menu_page_url(SimpleHistory::SETTINGS_MENU_SLUG, 0))
            				);
            */
        }
        ?>
			</p>
		</div>
		<?php 
    }
 function test_log_query()
 {
     // Add admin user
     $user_id = $this->factory->user->create(array('role' => 'administrator'));
     wp_set_current_user($user_id);
     $args = array("posts_per_page" => 1);
     $logQuery = new SimpleHistoryLogQuery();
     $queryResults = $logQuery->query($args);
     // The latest row should be the user we create above
     $this->assertArrayHasKey("total_row_count", $queryResults);
     $this->assertArrayHasKey("pages_count", $queryResults);
     $this->assertArrayHasKey("page_current", $queryResults);
     $this->assertArrayHasKey("page_rows_from", $queryResults);
     $this->assertArrayHasKey("page_rows_to", $queryResults);
     $this->assertArrayHasKey("max_id", $queryResults);
     $this->assertArrayHasKey("min_id", $queryResults);
     $this->assertArrayHasKey("log_rows_count", $queryResults);
     $this->assertArrayHasKey("log_rows", $queryResults);
     $this->assertCount(1, $queryResults["log_rows"]);
     $this->assertObjectHasAttribute("id", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("logger", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("level", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("date", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("message", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("initiator", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("occasionsID", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("subsequentOccasions", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("rep", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("repeated", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("occasionsIDType", $queryResults["log_rows"][0]);
     $this->assertObjectHasAttribute("context", $queryResults["log_rows"][0]);
 }
    public function downloadExport()
    {
        global $wpdb;
        $table_name = $wpdb->prefix . SimpleHistory::DBTABLE;
        $table_name_contexts = $wpdb->prefix . SimpleHistory::DBTABLE_CONTEXTS;
        if (isset($_POST["simple-history-action"]) && $_POST["simple-history-action"] === "export-history") {
            // Will die if nonce not valid
            check_admin_referer(__CLASS__ . "-action-export");
            $export_format = isset($_POST["format"]) ? $_POST["format"] : "json";
            // Disable relative time output in header
            add_filter("simple_history/header_time_ago_max_time", "__return_zero");
            add_filter("simple_history/header_just_now_max_time", "__return_zero");
            // Don't use "You" if event is initiated by the same user that does the export
            add_filter("simple_history/header_initiator_use_you", "__return_false");
            $query = new SimpleHistoryLogQuery();
            $query_args = array("paged" => 1, "posts_per_page" => 3000);
            $events = $query->query($query_args);
            // $events->total_row_count;
            $pages_count = $events["pages_count"];
            $page_current = $events["page_current"];
            $fp = fopen('php://output', 'w');
            #header("Content-Type: application/octet-stream");
            if ("csv" == $export_format) {
                $filename = "simple-history-export-" . time() . ".csv";
                header("Content-Type: text/plain");
                header("Content-Disposition: attachment; filename='{$filename}'");
            } else {
                if ("json" == $export_format) {
                    $filename = "simple-history-export-" . time() . ".json";
                    header("Content-Type: application/json");
                    header("Content-Disposition: attachment; filename='{$filename}'");
                } else {
                    if ("html" == $export_format) {
                        $filename = "simple-history-export-" . time() . ".html";
                        header("Content-Type: text/html");
                        #header("Content-Disposition: attachment; filename='{$filename}'");
                    }
                }
            }
            // Some formats need to output some stuff before the actual loops
            if ("json" == $export_format) {
                $json_row = "[";
                fwrite($fp, $json_row);
            } else {
                if ("html" == $export_format) {
                    $html = sprintf('
				<!doctype html>
				<meta charset="utf-8">
				<title>Simple History export</title>
				<ul>
				');
                    fwrite($fp, $html);
                }
            }
            // Paginate through all pages and all their rows
            $row_loop = 0;
            while ($page_current <= $pages_count + 1) {
                // if ($page_current > 1) { break; } # To debug/test
                foreach ($events["log_rows"] as $one_row) {
                    // if ( $row_loop > 10) { break; } # To debug/test
                    set_time_limit(30);
                    if ("csv" == $export_format) {
                        $header_output = strip_tags(html_entity_decode($this->sh->getLogRowHeaderOutput($one_row), ENT_QUOTES, 'UTF-8'));
                        $header_output = trim(preg_replace('/\\s\\s+/', ' ', $header_output));
                        $message_output = strip_tags(html_entity_decode($this->sh->getLogRowPlainTextOutput($one_row), ENT_QUOTES, 'UTF-8'));
                        fputcsv($fp, array($one_row->date, $one_row->logger, $one_row->level, $one_row->initiator, $one_row->context_message_key, $header_output, $message_output, $one_row->subsequentOccasions));
                    } else {
                        if ("json" == $export_format) {
                            // If not first loop then add a comma between all json objects
                            if ($row_loop == 0) {
                                $comma = "\n";
                            } else {
                                $comma = ",\n";
                            }
                            $json_row = $comma . $this->sh->json_encode($one_row);
                            fwrite($fp, $json_row);
                        } else {
                            if ("html" == $export_format) {
                                $html = sprintf('
							<li>
								<div>%1$s</div>
								<div>%2$s</div>
								<div>%3$s</div>
							</li>
							', $this->sh->getLogRowHeaderOutput($one_row), $this->sh->getLogRowPlainTextOutput($one_row), $this->sh->getLogRowDetailsOutput($one_row));
                                fwrite($fp, $html);
                            }
                        }
                    }
                    $row_loop++;
                }
                #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
                #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
                #echo "<br>fetch next page";
                flush();
                // Fetch next page
                // @TODO: must take into consideration that new items can be added while we do the fetch
                $page_current++;
                $query_args["paged"] = $page_current;
                $events = $query->query($query_args);
                #echo "<br>did fetch next page";
                #echo "<br>memory_get_usage:<br>"; print_r(memory_get_usage());
                #echo "<br>memory_get_peak_usage:<br>"; print_r(memory_get_peak_usage());
            }
            if ("json" == $export_format) {
                $json_row = "]";
                fwrite($fp, $json_row);
            } else {
                if ("html" == $export_format) {
                    $html = sprintf('</ul>');
                    fwrite($fp, $html);
                }
            }
            fclose($fp);
            flush();
            exit;
            #echo "<br>done";
        }
    }
    /**
     * Output RSS
     */
    function output_rss()
    {
        $rss_secret_option = get_option("simple_history_rss_secret");
        $rss_secret_get = isset($_GET["rss_secret"]) ? $_GET["rss_secret"] : "";
        if (empty($rss_secret_option) || empty($rss_secret_get)) {
            die;
        }
        $rss_show = true;
        $rss_show = apply_filters("simple_history/rss_feed_show", $rss_show);
        if (!$rss_show || !$this->is_rss_enabled()) {
            wp_die('Nothing here.');
        }
        header("Content-Type: text/xml; charset=utf-8");
        echo '<?xml version="1.0" encoding="UTF-8"?>';
        $self_link = $this->get_rss_address();
        if ($rss_secret_option === $rss_secret_get) {
            ?>
				<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
					<channel>
						<title><![CDATA[<?php 
            printf(__("History for %s", 'simple-history'), get_bloginfo("name"));
            ?>
]]></title>
						<description><![CDATA[<?php 
            printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name"));
            ?>
]]></description>
						<link><?php 
            echo get_bloginfo("url");
            ?>
</link>
						<atom:link href="<?php 
            echo $self_link;
            ?>
" rel="self" type="application/atom+xml" />
						<?php 
            // Override capability check: if you have a valid rss_secret_key you can read it all
            $action_tag = "simple_history/loggers_user_can_read/can_read_single_logger";
            add_action($action_tag, array($this, "on_can_read_single_logger"), 10, 3);
            // Modify header time output so it does not show relative date or time ago-format
            // Because we don't know when a user reads the RSS feed, time ago format may be very inaccurate
            add_action("simple_history/header_just_now_max_time", "__return_zero");
            add_action("simple_history/header_time_ago_max_time", "__return_zero");
            // Get log rows
            $args = array("posts_per_page" => 10);
            $args = apply_filters("simple_history/rss_feed_args", $args);
            $logQuery = new SimpleHistoryLogQuery();
            $queryResults = $logQuery->query($args);
            // Remove capability override after query is done
            // remove_action( $action_tag, array($this, "on_can_read_single_logger") );
            foreach ($queryResults["log_rows"] as $row) {
                $header_output = $this->sh->getLogRowHeaderOutput($row);
                $text_output = $this->sh->getLogRowPlainTextOutput($row);
                $details_output = $this->sh->getLogRowDetailsOutput($row);
                // http://cyber.law.harvard.edu/rss/rss.html#ltguidgtSubelementOfLtitemgt
                //$item_guid = home_url() . "?SimpleHistoryGuid=" . $row->id;
                $item_guid = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
                $item_link = esc_url(add_query_arg("SimpleHistoryGuid", $row->id, home_url()));
                /**
                 * Filter the guid/link URL used in RSS feed.
                 * Link will be esc_url'ed by simple history, so no need to do that in your filter
                 *
                 * @since 2.0.23
                 *
                 * @param string $item_guid link.
                 * @param array $row
                 */
                $item_link = apply_filters("simple_history/rss_item_link", $item_link, $row);
                $item_link = esc_url($item_link);
                $item_title = $this->sh->getLogLevelTranslated($row->level) . ": " . wp_kses($text_output, array());
                $level_output = sprintf(__('Severity level: %1$s'), $this->sh->getLogLevelTranslated($row->level));
                ?>
							<item>
								<title><![CDATA[<?php 
                echo $item_title;
                ?>
]]></title>
								<description><![CDATA[
									<p><?php 
                echo $header_output;
                ?>
</p>
									<p><?php 
                echo $text_output;
                ?>
</p>
									<div><?php 
                echo $details_output;
                ?>
</div>
									<p><?php 
                echo $level_output;
                ?>
</p>
									<?php 
                $occasions = $row->subsequentOccasions - 1;
                if ($occasions) {
                    printf(_n('+%1$s occasion', '+%1$s occasions', $occasions, 'simple-history'), $occasions);
                }
                ?>
								]]></description>
								<?php 
                // author must be email to validate, but the field is optional, so we skip it
                /* <author><?php echo $row->initiator ?></author> */
                ?>
								<pubDate><?php 
                echo date("D, d M Y H:i:s", strtotime($row->date));
                ?>
 GMT</pubDate>
								<guid isPermaLink="false"><![CDATA[<?php 
                echo $item_guid;
                ?>
]]></guid>
								<link><![CDATA[<?php 
                echo $item_link;
                ?>
]]></link>
							</item>
							<?php 
                /*
                				            [0] =&gt; stdClass Object
                				                (
                				                    [id] =&gt; 27324
                				                    [logger] =&gt; SimplePluginLogger
                				                    [level] =&gt; info
                				                    [date] =&gt; 2014-10-15 06:50:01
                				                    [message] =&gt; Updated plugin &quot;{plugin_name}&quot; from {plugin_prev_version} to {plugin_version}
                				                    [type] =&gt;
                				                    [initiator] =&gt; wp_user
                				                    [occasionsID] =&gt; 75e8aeab3e43b37f8a458f3744c4995f
                				                    [subsequentOccasions] =&gt; 1
                				                    [rep] =&gt; 1
                				                    [repeated] =&gt; 1
                				                    [occasionsIDType] =&gt; 75e8aeab3e43b37f8a458f3744c4995f
                				                    [context] =&gt; Array
                				                        (
                				                            [plugin_slug] =&gt; google-analytics-for-wordpress
                				                            [plugin_name] =&gt; Google Analytics by Yoast
                				                            [plugin_title] =&gt; &lt;a href=&quot;https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&amp;#038;utm_medium=plugin&amp;#038;utm_campaign=wpgaplugin&amp;#038;utm_content=v504&quot;&gt;Google Analytics by Yoast&lt;/a&gt;
                				                            [plugin_description] =&gt; This plugin makes it simple to add Google Analytics to your WordPress blog, adding lots of features, eg. error page, search result and automatic clickout and download tracking. &lt;cite&gt;By &lt;a href=&quot;https://yoast.com/&quot;&gt;Team Yoast&lt;/a&gt;.&lt;/cite&gt;
                				                            [plugin_author] =&gt; &lt;a href=&quot;https://yoast.com/&quot;&gt;Team Yoast&lt;/a&gt;
                				                            [plugin_version] =&gt; 5.0.7
                				                            [plugin_url] =&gt; https://yoast.com/wordpress/plugins/google-analytics/#utm_source=wordpress&amp;#038;utm_medium=plugin&amp;#038;utm_campaign=wpgaplugin&amp;#038;utm_content=v504
                				                            [plugin_update_info_plugin] =&gt; google-analytics-for-wordpress/googleanalytics.php
                				                            [plugin_update_info_package] =&gt; https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.5.0.7.zip
                				                            [plugin_prev_version] =&gt; 5.0.6
                				                            [_message_key] =&gt; plugin_bulk_updated
                				                            [_user_id] =&gt; 1
                				                            [_user_login] =&gt; admin
                				                            [_user_email] =&gt; par.thernstrom@gmail.com
                				                            [_server_remote_addr] =&gt; ::1
                				                            [_server_http_referer] =&gt; http://playground-root.ep/wp-admin/update-core.php?action=do-plugin-upgrade
                				                        )
                
                				                )
                */
            }
            ?>
					</channel>
				</rss>
				<?php 
        } else {
            // RSS secret was not ok
            ?>
				<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
					<channel>
						<title><?php 
            printf(__("History for %s", 'simple-history'), get_bloginfo("name"));
            ?>
</title>
						<description><?php 
            printf(__("WordPress History for %s", 'simple-history'), get_bloginfo("name"));
            ?>
</description>
						<link><?php 
            echo home_url();
            ?>
</link>
						<item>
							<title><?php 
            _e("Wrong RSS secret", 'simple-history');
            ?>
</title>
							<description><?php 
            _e("Your RSS secret for Simple History RSS feed is wrong. Please see WordPress settings for current link to the RSS feed.", 'simple-history');
            ?>
</description>
							<pubDate><?php 
            echo date("D, d M Y H:i:s", time());
            ?>
 GMT</pubDate>
							<guid><?php 
            echo home_url() . "?SimpleHistoryGuid=wrong-secret";
            ?>
</guid>
						</item>
					</channel>
				</rss>
				<?php 
        }
    }
		});


	});

</script>
<?php 
defined('ABSPATH') or exit;
echo "<hr>";
echo "<p class='hide-if-no-js'><button class='button js-SimpleHistoryShowsStatsForGeeks'>Show stats for geeks</button></p>";
?>

<div class="SimpleHistory__statsForGeeksInner hide-if-js">
	<?php 
echo "<h4>Rows count</h4>";
$logQuery = new SimpleHistoryLogQuery();
$rows = $logQuery->query(array("posts_per_page" => 1));
// This is the number of rows with occasions taken into consideration
$total_accassions_rows_count = $rows["total_row_count"];
// Total number of log rows
// Not caring about occasions, this number = all occasions
$total_num_rows = $wpdb->get_var("select count(*) FROM {$table_name}");
echo "<ul>";
echo "<li>Total {$total_num_rows} log rows in db.</li>";
echo "<li>Total {$total_accassions_rows_count} rows, when grouped by occasion id.</li>";
echo "</ul>";
echo "<h4>Clear history interval</h4>";
echo "<p>" . $this->sh->get_clear_history_interval() . "</p>";
$sql_table_size = sprintf('
		SELECT table_name AS "table_name", 
		round(((data_length + index_length) / 1024 / 1024), 2) "size_in_mb"