<?php
namespace Fabrica\Dashboard;

if (!defined('WPINC')) { die(); }

require_once('base.php');

class ContentActivity {
	private static $posts;
	private static $filters;
	private static $columns;
	private static $count = 10;

	public static function init() {
		add_action('wp_dashboard_setup', array(__CLASS__, 'register'));
		add_action('wp_ajax_fd-content-activity-filter', array(__CLASS__, 'displayAjaxFilter'));
		add_action('wp_ajax_fd-content-activity-more', array(__CLASS__, 'displayAjaxMore'));
	}

	// Register
	public static function register() {
		add_meta_box('fd_content_activity', __("Content Activity", Base::$textDomain), array(__CLASS__, 'displayWrapper'), 'dashboard', 'side', 'high');
	}

	// Display table according to selected filters
	public static function displayAjaxFilter() {
		header('Content-Type: text/html');

		// Retrieve the data and sanitized filters
		self::cacheResults();

		// Return the requested results
		self::displayTable();
		exit;
	}

	// Update table with extra results when requested via AJAX
	public static function displayAjaxMore() {
		header('Content-Type: text/html');

		// Retrieve the data and sanitized filters
		self::cacheResults();

		// Return the requested results
		self::displayResults();
		exit;
	}


	// Display wrapper which in turn calls displayResults() to populate the table (which can also be called to load more by AJAX)
	public static function displayWrapper() {

		// Show fewer comments initially if Comments Activity will be visible too
		$defaultCount = self::$count;
		if (Base::$hasComments) {
			self::$count = 5;
		}

		// Retrieve the data and sanitized filters
		self::cacheResults();

		// Get all users for dropdown
		$args = array(
			'blog_id' => get_current_blog_id(),
			'role__in' => array('author', 'editor', 'administrator')
		);
		$authors = array_unique(get_users($args), SORT_REGULAR); // get_users() occasionally returns duplicates

		// Render wrapper
		?><div class="fd-util-center fd-util-margin-bottom">
			<div class="fd-content-activity-form fd-ajaxForm">
				<span class="fd-content-activity-form__label"><?php esc_html_e("Show", Base::$textDomain); ?></span>
				<select class="fd-content-activity-form__select fd-ajaxFormSelect" id="fd-content-activity-type" name="data[fd-content-activity-type]"><option value="all"><?php esc_html_e("all content", Base::$textDomain); ?></option><?php
					foreach (Base::$postTypes as $type => $labels) {
						if ($type == 'attachment') { // Don't include Media here
							continue;
						}
						?><option value="<?php echo esc_attr($type); ?>" <?php if (self::$filters['type'] == $type) { echo 'selected'; } ?>>&nbsp;&nbsp;&nbsp;<?php echo esc_html($labels['plural']); ?></option><?php
					}
				?></select><select class="fd-content-activity-form__select fd-ajaxFormSelect" id="fd-content-activity-action" name="data[fd-content-activity-action]">
					<option value="all"><?php esc_html_e("created / edited", Base::$textDomain); ?></option>
					<option value="created" <?php if (self::$filters['action'] == 'created') { echo 'selected'; } ?>>&nbsp;&nbsp;&nbsp;<?php esc_html_e("created", Base::$textDomain); ?></option>
					<option value="edited" <?php if (self::$filters['action'] == 'edited') { echo 'selected'; } ?>>&nbsp;&nbsp;&nbsp;<?php esc_html_e("edited", Base::$textDomain); ?></option>
					<option value="scheduled" <?php if (self::$filters['action'] == 'scheduled') { echo 'selected'; } ?>><?php esc_html_e("scheduled", Base::$textDomain); ?></option>
				</select><?php
				if (Base::$isEditor && Base::$totalUsers > 1) {
					?><br>
					<span class="fd-content-activity-form__label">by</span>
					<select class="fd-content-activity-form__select fd-ajaxFormSelect" id="fd-content-activity-author" name="data[fd-content-activity-author]"><option value="all"><?php esc_html_e("all users", Base::$textDomain); ?></option>
						<option value="<?php echo esc_attr(Base::$currentUser->ID); ?>" <?php if (self::$filters['author'] == Base::$currentUser->ID) { echo 'selected'; } ?>>&nbsp;&nbsp;&nbsp;you (<?php echo esc_html(Base::$currentUser->data->display_name); ?>)</option><?php
						foreach ($authors as $author) {
							if ($author->ID == Base::$currentUser->ID) {
								continue;
							}
							?><option value="<?php echo esc_attr($author->ID); ?>" <?php if (self::$filters['author'] == $author->ID) { echo 'selected'; } ?>>&nbsp;&nbsp;&nbsp;<?php
								echo esc_html($author->data->display_name);
							?></option><?php
						}
					?></select><?php
				}
				?><select class="fd-content-activity-form__select fd-ajaxFormSelect" id="fd-content-activity-time" name="data[fd-content-activity-time]">
					<option value="whenever">most recently</option>
					<option value="lastweek" <?php if (self::$filters['time'] == 'lastweek') { echo 'selected'; } ?>><?php esc_html_e("during the last week", Base::$textDomain); ?></option>
					<option value="lastmonth" <?php if (self::$filters['time'] == 'lastmonth') { echo 'selected'; } ?>><?php esc_html_e("during the last month", Base::$textDomain); ?></option>
				</select><?php
				$params = json_encode(array(
					'fd-content-activity-type' => self::$filters['type'],
					'fd-content-activity-action' => self::$filters['action'],
					'fd-content-activity-author' => self::$filters['author'],
					'fd-content-activity-time' => self::$filters['time'],
					'fd-content-activity-offset' => 0
				));
				?><div class="fd-util-clearfix"><button class="button fd-util-float-right fd-util-margin-bottom fd-ajaxButton" data-ajax-action="fd-content-activity-filter" data-ajax-params='<?php echo esc_attr($params); ?>'><?php esc_html_e("Filter", Base::$textDomain); ?></button></div>
			</div>
		</div><?php
		self::displayTable();
	}

	// Display table frame
	public static function displayTable() {
		?><table class="wp-list-table widefat striped fd-util-normal-table" id="fd-content-activity-table" data-ajax-replace="fd-content-activity-table">
			<thead><?php
				if (self::$filters['action'] == 'scheduled') {
					?><th><?php esc_html_e("For", Base::$textDomain); ?></th><?php
				} else {
					?><th><?php esc_html_e("Date", Base::$textDomain); ?></th><?php
				}

				// If all content types shown, show both Type and Title columns, otherwise just Title
				if (self::$filters['type'] == 'all') {
					?><th><?php esc_html_e("Type", Base::$textDomain); ?></th>
					<th><?php esc_html_e("Title", Base::$textDomain); ?></th><?php
				} else {
					?><th><?php echo esc_html(Base::$postTypes[self::$filters['type']]['singular']) . ' ' . esc_html__("title", Base::$textDomain); ?></th><?php
				}

				// If created or edited selected specifically, use those as the column header (only show author in body)
				if (self::$filters['author'] == 'all' && self::$filters['action'] == 'created' && Base::$totalUsers > 1) {
					?><th><?php esc_html_e("Created by", Base::$textDomain); ?></th><?php
				} else if (self::$filters['author'] == 'all' && self::$filters['action'] == 'edited' && Base::$totalUsers > 1) {
					?><th><?php esc_html_e("Edited by", Base::$textDomain); ?></th><?php
				} else if (self::$filters['author'] != 'all' && self::$filters['action'] != 'all') {
					?><th></th><?php // May show View Revision in the <td> even if no other data shown
				} else {
					?><th><?php esc_html_e("Action", Base::$textDomain); ?></th><?php
				}
			?></thead>
			<tbody><?php
				self::displayResults();
			?></tbody>
		</table><?php
	}

	// Perform query (on load) and cache for use by either normal display or AJAX display
	private static function cacheResults() {

		// Default filters
		$filters = array(
			'action' => 'all',
			'type' => 'all',
			'author' => 'all',
			'time' => 'all',
			'offset' => 0
		);
		if (!Base::$isEditor || Base::$totalUsers == 1) {
			$filters['author'] = Base::$currentUser->ID;
		}

		// Override defaults with any chosen filters, sanitizing
		if (isset($_POST['data'])) {
			$params = $_POST['data'];

			// Post type
			if (isset($params['fd-content-activity-type'])) {
				$filters['type'] = $params['fd-content-activity-type'];
			}

			// Action
			if (isset($params['fd-content-activity-action']) && ($params['fd-content-activity-action'] == 'created' || $params['fd-content-activity-action'] == 'edited' || $params['fd-content-activity-action'] == 'scheduled')) {
				$filters['action'] = $params['fd-content-activity-action'];
			}

			// Author
			if (!Base::$isEditor || Base::$totalUsers == 1) {
				$filters['author'] = Base::$currentUser->ID;
			} else if (isset($params['fd-content-activity-author']) && $params['fd-content-activity-author'] != 'all') {
				$filters['author'] = $params['fd-content-activity-author'];
			}

			// Time
			if (isset($params['fd-content-activity-time']) && ($params['fd-content-activity-time'] == 'lastweek' || $params['fd-content-activity-time'] == 'lastmonth')) {
				$filters['time'] = $params['fd-content-activity-time'];
			}

			// Query offset
			if (isset($params['fd-content-activity-offset']) && is_numeric($params['fd-content-activity-offset'])) {
				$filters['offset'] = $params['fd-content-activity-offset'];
			}
		}

		// Default query
		$queryValues = array();
		$query = 'SELECT ID, post_modified, post_date, post_type, post_title, post_parent, post_author FROM ' . Base::$dbPrefix . 'posts';
		if ($filters['author'] != 'all' && ($filters['action'] == 'edited' || $filters['action'] == 'all')) {

			// Meta fields will be needed for filtering too
			$query .= ' LEFT JOIN ' . Base::$dbPrefix . 'postmeta ON (' . Base::$dbPrefix . 'posts.ID = ' . Base::$dbPrefix . 'postmeta.post_id AND ' . Base::$dbPrefix . 'postmeta.meta_key = \'_edit_last\')';
		}
		$query .= ' WHERE 1=1';

		// Add filters to query

		// Post types
		if ($filters['type'] != 'all') {
			$queryValues[] = $filters['type'];
			$query .= ' AND post_type = %s';
		} else {
			// Restrict to relevant post types
			$query .= ' AND post_type IN (\'' . join('\', \'', array_keys(Base::$postTypes)) . '\')';
		}

		// Statuses
		if ($filters['action'] == 'scheduled') {
			$query .= ' AND post_status =\'future\' AND post_date_gmt > NOW()';
		} else {
			$query .= ' AND (post_status IN (\'publish\', \'future\', \'draft\', \'pending\')';
			if ($filters['author'] == 'all') {
				$query .= ' OR (post_status = \'private\' AND post_author = ' . Base::$currentUser->ID . ')';
			}
			$query .= ')';
		}

		// Author
		if ($filters['author'] != 'all') {
			$query .= ' AND (';
			if ($filters['action'] == 'created' || $filters['action'] == 'scheduled' || $filters['action'] == 'all') {
				$queryValues[] = $filters['author'];
				$query .= 'post_author = %s';
			}
			if ($filters['action'] == 'edited' || $filters['action'] == 'all') {
				$queryValues[] = $filters['author'];
				if ($filters['action'] == 'all') {
					$query .= ' OR ';
				}
				$query .= Base::$dbPrefix . 'postmeta.meta_value = %s';
			}
			$query .= ')';
		}

		// Time of creation or publication
		if ($filters['time'] != 'all') {
			if ($filters['time'] == 'lastweek') {
				$after = strtotime('1 week ago');
			} else if ($filters['time'] == 'lastmonth') {
				$after = strtotime('1 month ago');
			}
			$createdClause = '(post_date_gmt > %s AND post_date_gmt < NOW())'; // Don't allow scheduled posts to appear as recently created
			$editedClause = 'post_modified_gmt > %s';
			if ($filters['action'] == 'created') {
				$queryValues[] = date('Y-m-d H:i:s', $after);
				$query .= ' AND ' . $createdClause;
			} else if ($filters['action'] == 'edited' || $filters['action'] == 'scheduled') {
				$queryValues[] = date('Y-m-d H:i:s', $after);
				$query .= ' AND ' . $editedClause;
			} else { // created / edited
				$queryValues[] = date('Y-m-d H:i:s', $after);
				$queryValues[] = date('Y-m-d H:i:s', $after);
				$query .= ' AND (' . $createdClause . ' OR ' . $editedClause . ')';
			}
		}

		// Do the relevant query
		// If 'created' posts selected only, order by creation date (not modified date)
		if ($filters['action'] == 'created') {
			$query .= ' ORDER BY post_date_gmt DESC';
		} else if ($filters['action'] == 'scheduled') {
			$query .= ' ORDER BY post_date_gmt ASC';
		} else {
			$query .= ' ORDER BY post_modified_gmt DESC';
		}
		$queryValues[] = $filters['offset'];
		$queryValues[] = self::$count + 1;
		$query .= ' LIMIT %d, %d';

		global $wpdb;
		if (count($queryValues) > 0) {
			$query = $wpdb->prepare($query, $queryValues);
		}

		// Cache the filters and results for use by other functions
		self::$filters = $filters;
		if (self::$filters['type'] == 'all') { // Number of columns in the table, needed for colspan later
			self::$columns = 4;
		} else {
			self::$columns = 3;
		}
		self::$posts = $wpdb->get_results($query);
	}

	// Display results
	private static function displayResults() {

		// Start a counter - first and last rows will have some special markup relevant to AJAX requests
		$c = 0;

		if (count(self::$posts) == 0) {
			?><tr id="fd-content-activity" <?php if ($c == 0) { echo ' data-ajax-replace="fd-content-activity-loadmore"'; } ?>>
				<td colspan="<?php echo esc_attr(self::$columns); ?>"><?php esc_html_e("There is no activity that fits the chosen criteria.", Base::$textDomain); ?></td>
			</tr><?php
		} else {
			$yearAgo = strtotime('1 year ago');
			$yearFromNow = strtotime('+1 year');
			foreach (self::$posts as $post) {
				if ($c == self::$count) { // If there's an additional item, show 'show more' button

					// Encode the filters to be sent with the AJAX request
					$params = json_encode(array(
						'fd-content-activity-type' => self::$filters['type'],
						'fd-content-activity-action' => self::$filters['action'],
						'fd-content-activity-author' => self::$filters['author'],
						'fd-content-activity-time' => self::$filters['time'],
						'fd-content-activity-offset' => self::$filters['offset'] + count(self::$posts) - 1
					));
					?><tr id="fd-content-activity-loadmore">
						<td colspan="<?php echo esc_attr(self::$columns); ?>" class="fd-util-center">
							<button class="button fd-ajaxButton" data-ajax-action="fd-content-activity-more" data-ajax-params='<?php echo esc_attr($params); ?>'><?php esc_html_e("Show more", Base::$textDomain); ?></button>
						</td>
					</tr><?php
				} else {
					?><tr<?php if ($c == 0) { echo ' data-ajax-replace="fd-content-activity-loadmore"'; } ?>>
						<td><?php
							if (self::$filters['action'] == 'scheduled') {
								$date = strtotime($post->post_date);
								echo esc_html(date($date < $yearFromNow ? 'j M' : 'j M y', $date));
							} else {
								$date = strtotime(self::$filters['action'] == 'created' ? $post->post_date : $post->post_modified);
								echo $date > $yearAgo ? esc_html(date('j M', $date)) : wp_kses_post(Base::ago($date));
							}
						?></td><?php
						if (self::$filters['type'] == 'all') {
							?><td><?php echo esc_html(Base::$postTypes[$post->post_type]['singular']); ?></td><?php
						} ?>
						<td><a href="<?php echo esc_attr(get_edit_post_link($post->ID)); ?>"><?php echo esc_html($post->post_title); ?></a></td>
						<td><?php
							// Default values
							$action = self::$filters['action'];
							$latestRevision = current(wp_get_post_revisions($post->ID, array('posts_per_page' => 1)));
							$latestAuthor = !empty($latestRevision) ? $latestRevision->post_author : '';
							if (self::$filters['action'] == 'created') {
								$author = $post->post_author;
							} else if (self::$filters['action'] == 'edited') {
								$author = $latestAuthor;
							} else if ($post->post_date == $post->post_modified || self::$filters['author'] != 'all' && self::$filters['author'] != $latestAuthor) {
								// Post has never been modified or filtered user is not the editor of latest post
								$author = $post->post_author;
								$action = 'created';
								$actionLabel = __('created', Base::$textDomain);
							} else {
								$author = $latestAuthor;
								$action = 'edited';
								$actionLabel = __('edited', Base::$textDomain);
							}
							$author = get_the_author_meta('display_name', $author);
							if (self::$filters['action'] == 'all') {
								echo esc_html($actionLabel);
							}
							if (self::$filters['action'] == 'all' && self::$filters['author'] == 'all' && $author && Base::$totalUsers > 1) {
								echo ' ' . esc_html__('by', Base::$textDomain) . ' ';
							}
							if (self::$filters['author'] == 'all' && $author && Base::$totalUsers > 1) {
								echo esc_html($author);
							}
							if (self::$filters['action'] == 'all' || ($author && self::$filters['author'] == 'all' && Base::$totalUsers > 1)) {
								echo '<br>';
							}
							if ($action == 'edited' && !empty($latestRevision)) {
								echo ' <a href="' . esc_attr(admin_url('revision.php?revision=' . $latestRevision->ID)) . '">View revision</a>';
							}
						?></td>
					</tr><?php
				}
				$c++;
			}
		}
	}
}
ContentActivity::init();
