/** * Returns whether payload should be imported. * * @return bool */ public function should_import() { // @todo how do we get this without importing the whole api object just for this? if (strtolower($this->data->repository->full_name) !== strtolower($this->app->api()->fetch()->repository())) { return false; } // The last term in the ref is the payload_branch name. $refs = explode('/', $this->data->ref); $payload_branch = array_pop($refs); $sync_branch = apply_filters('wpghs_sync_branch', 'master'); if (!$sync_branch) { throw new Exception(__('Sync branch not set. Filter `wpghs_sync_branch` misconfigured.', 'wordpress-github-sync')); } if ($sync_branch !== $payload_branch) { return false; } // We add a tag to commits we push out, so we shouldn't pull them in again. $tag = apply_filters('wpghs_commit_msg_tag', 'wpghs'); if (!$tag) { throw new Exception(__('Commit message tag not set. Filter `wpghs_commit_msg_tag` misconfigured.', 'wordpress-github-sync')); } if ($tag === substr($this->message(), -1 * strlen($tag))) { return false; } return true; }
/** * Writes a log message. * * Can extract a message from WP_Error object. * * @param string|WP_Error $msg Message to log. */ protected function log($msg) { if (is_wp_error($msg)) { $msg = $msg->get_error_message(); } WordPress_GitHub_Sync::write_log($msg); }
/** * Imports a single blob content into matching post. * * @param WordPress_GitHub_Sync_Blob $blob Blob to transform into a Post. * * @return WordPress_GitHub_Sync_Post */ protected function blob_to_post(WordPress_GitHub_Sync_Blob $blob) { $args = array('post_content' => $blob->content_import()); $meta = $blob->meta(); if ($meta) { if (array_key_exists('layout', $meta)) { $args['post_type'] = $meta['layout']; unset($meta['layout']); } if (array_key_exists('published', $meta)) { $args['post_status'] = true === $meta['published'] ? 'publish' : 'draft'; unset($meta['published']); } if (array_key_exists('post_title', $meta)) { $args['post_title'] = $meta['post_title']; unset($meta['post_title']); } if (array_key_exists('ID', $meta)) { $args['ID'] = $meta['ID']; unset($meta['ID']); } } $meta['_sha'] = $blob->sha(); $post = new WordPress_GitHub_Sync_Post($args, $this->app->api()); $post->set_meta($meta); return $post; }
/** * Queries for a post by provided sha. * * @param string $sha Post sha to fetch by. * * @return WordPress_GitHub_Sync_Post|WP_Error */ public function fetch_by_sha($sha) { $query = new WP_Query(array('meta_key' => '_sha', 'meta_value' => $sha, 'meta_compare' => '=', 'posts_per_page' => 1, 'fields' => 'ids')); $post_id = $query->get_posts(); $post_id = array_pop($post_id); if (!$post_id) { return new WP_Error('sha_not_found', sprintf(__('Post for sha %s not found.', 'wordpress-github-sync'), $sha)); } return new WordPress_GitHub_Sync_Post($post_id, $this->app->api()); }
/** * Removes the post from the tree. * * Called the delete_post hook. * * @param int $post_id Post ID. * * @return boolean */ public function delete_post($post_id) { if (!$this->app->semaphore()->is_open()) { return $this->app->response()->error(new WP_Error('semaphore_locked', sprintf(__('%s : Semaphore is locked, import/export already in progress.', 'wordpress-github-sync'), 'Controller::delete_post()'))); } $this->app->semaphore()->lock(); $result = $this->app->export()->delete($post_id); $this->app->semaphore()->unlock(); if (is_wp_error($result)) { return $this->app->response()->error($result); } return $this->app->response()->success($result); }
/** * Fetches the provided sha or the repository's * master branch and caches it. * * ## OPTIONS * * <user_id> * : The user ID you'd like to save the commit as * * ## EXAMPLES * * wp wpghs prime --branch=master * wp wpghs prime --sha=<commit_sha> * * @synopsis [--sha=<commit_sha>] [--branch] * * @param array $args Command arguments. * @param array $assoc_args Command associated arguments. */ public function prime($args, $assoc_args) { if (isset($assoc_args['branch'])) { WP_CLI::line(__('Starting branch import.', 'wordpress-github-sync')); $commit = $this->app->api()->fetch()->master(); if (is_wp_error($commit)) { WP_CLI::error(sprintf(__('Failed to import and cache branch with error: %s', 'wordpress-github-sync'), $commit->get_error_message())); } else { WP_CLI::success(sprintf(__('Successfully imported and cached commit %s from branch.', 'wordpress-github-sync'), $commit->sha())); } } else { if (isset($assoc_args['sha'])) { WP_CLI::line('Starting sha import.'); $commit = $this->app->api()->fetch()->commit($assoc_args['sha']); WP_CLI::success(sprintf(__('Successfully imported and cached commit %s.', 'wordpress-github-sync'), $commit->sha())); } else { WP_CLI::error('Invalid fetch.'); } } }
/** * Use the new tree to save sha data * for all the updated posts. * * @param WordPress_GitHub_Sync_Post[] $posts Posts to fetch updated shas for. * * @return string|WP_Error */ protected function update_shas(array $posts) { $master = $this->app->api()->fetch()->master(); $attempts = 1; while (is_wp_error($master) && $attempts < 5) { $master = $this->app->api()->fetch()->master(); $attempts++; } if (is_wp_error($master)) { // @todo throw a big warning! not having the latest shas is BAD // Solution: Show error message and link to kick off sha importing. return $master; } foreach ($posts as $post) { $blob = $master->tree()->get_blob_by_path($post->github_path()); if ($blob) { $this->app->database()->set_post_sha($post, $blob->sha()); } } return __('Export to GitHub completed successfully.', 'wordpress-github-sync'); }
/** * Called at load time, hooks into WP core */ public function __construct() { self::$instance = $this; if (is_admin()) { $this->admin = new WordPress_GitHub_Sync_Admin(); } $this->controller = new WordPress_GitHub_Sync_Controller($this); if (defined('WP_CLI') && WP_CLI) { WP_CLI::add_command('wpghs', $this->cli()); } }
/** * Imports a single blob content into matching post. * * @param stdClass $blob */ protected function import_blob($blob) { // Break out meta, if present preg_match('/(^---(.*?)---$)?(.*)/ms', $blob->content, $matches); $body = array_pop($matches); if (3 === count($matches)) { $meta = cyps_load($matches[2]); if (isset($meta['permalink'])) { $meta['permalink'] = str_replace(home_url(), '', get_permalink($meta['permalink'])); } } else { $meta = array(); } if (function_exists('wpmarkdown_markdown_to_html')) { $body = wpmarkdown_markdown_to_html($body); } $args = array('post_content' => apply_filters('wpghs_content_import', $body)); if (!empty($meta)) { if (array_key_exists('layout', $meta)) { $args['post_type'] = $meta['layout']; unset($meta['layout']); } if (array_key_exists('published', $meta)) { $args['post_status'] = true === $meta['published'] ? 'publish' : 'draft'; unset($meta['published']); } if (array_key_exists('post_title', $meta)) { $args['post_title'] = $meta['post_title']; unset($meta['post_title']); } if (array_key_exists('ID', $meta)) { $args['ID'] = $meta['ID']; unset($meta['ID']); } } if (!isset($args['ID'])) { // @todo create a revision when we add revision author support $post_id = wp_insert_post($args); } else { $post_id = wp_update_post($args); } /** @var WordPress_GitHub_Sync_Post $post */ $post = new WordPress_GitHub_Sync_Post($post_id); $post->set_sha($blob->sha); foreach ($meta as $key => $value) { update_post_meta($post_id, $key, $value); } WordPress_GitHub_Sync::write_log(__('Updated blob ', 'wordpress-github-sync') . $blob->sha); }
/** * Sets and kicks off the import cronjob */ public function start_import() { update_option('_wpghs_import_started', 'yes'); WordPress_GitHub_Sync::write_log(__('Starting import from GitHub.', WordPress_GitHub_Sync::$text_domain)); wp_schedule_single_event(time(), 'wpghs_import'); spawn_cron(); }
/** * Retrieve the saved tree we're building * or get the latest tree from the repo */ public function get_tree() { if (!empty($this->tree)) { return; } $tree = $this->api->last_tree_recursive(); if (is_wp_error($tree)) { WordPress_GitHub_Sync::write_log(__('Failed getting tree with error: ', WordPress_GitHub_Sync::$text_domain) . $tree->get_error_message()); return; } $this->tree = $tree; }
/** * Export all the posts in the database to GitHub */ public function export_all() { global $wpdb; if ($this->locked()) { WordPress_GitHub_Sync::write_log(__('Export locked. Terminating.', 'wordpress-github-sync')); return; } $post_statuses = $this->format_for_query($this->get_whitelisted_post_statuses()); $post_types = $this->format_for_query($this->get_whitelisted_post_types()); $post_ids = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE\n\t\t\tpost_status IN ( {$post_statuses} ) AND\n\t\t\tpost_type IN ( {$post_types} )"); $msg = apply_filters('wpghs_commit_msg_full', 'Full export from WordPress at ' . site_url() . ' (' . get_bloginfo('name') . ')') . ' - wpghs'; $export = new WordPress_GitHub_Sync_Export($post_ids, $msg); $export->run(); }
/** * Writes out the results of a successful export */ public function success() { update_option('_wpghs_export_complete', 'yes'); update_option('_wpghs_fully_exported', 'yes'); WordPress_GitHub_Sync::write_log(__('Export to GitHub completed successfully.', 'wordpress-github-sync'), 'success'); }
/** * Checks if current position is valid * * @link http://php.net/manual/en/iterator.valid.php * @return boolean true on success, false on failure. */ public function valid() { global $wpdb; while (isset($this->tree[$this->position])) { $blob = $this->tree[$this->position]; // Skip the repo's readme if ('readme' === strtolower(substr($blob->path, 0, 6))) { WordPress_GitHub_Sync::write_log(__('Skipping README', 'wordpress-github-sync')); $this->next(); continue; } // If the blob sha already matches a post, then move on $id = $wpdb->get_var("SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_sha' AND meta_value = '{$blob->sha}'"); if ($id) { WordPress_GitHub_Sync::write_log(sprintf(__('Already synced blob %s', 'wordpress-github-sync'), $blob->path)); $this->next(); continue; } $blob = $this->api->get_blob($blob->sha); if (is_wp_error($blob)) { WordPress_GitHub_Sync::write_log(sprintf(__('Failed getting blob with error: %s', 'wordpress-github-sync'), $blob->get_error_message())); $this->next(); continue; } $content = base64_decode($blob->content); // If it doesn't have YAML frontmatter, then move on if ('---' !== substr($content, 0, 3)) { WordPress_GitHub_Sync::write_log(sprintf(__('No front matter on blob %s', 'wordpress-github-sync'), $blob->sha)); $this->next(); continue; } $blob->content = $content; $this->current = $blob; return true; } return false; }