Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

adding proper svn structure

  • Loading branch information...
commit 58a354d45839a22337aefa0cf242a062887d80de 0 parents
sparker authored
31 README.txt
... ... @@ -0,0 +1,31 @@
  1 +# CF Revision Manager
  2 +
  3 +The CF Revision Manager will take registered post meta fields and version them when post-revisions are made. The post-meta is duplicated and attached to the specific post-revision that is made. Registered post meta items will appear in the post-revision inspection screen. Post meta items do not show up in the post-comparison feature.
  4 +
  5 +## Registering Your Post Meta
  6 +
  7 +The CFR plugin includes a registration function to easily include your post-meta in the revision scheme.
  8 +
  9 + function my_registered_post_meta_item() {
  10 + if (function_exists('cfr_register_metadata')) {
  11 + cfr_register_metadata('my_metadata_key');
  12 + }
  13 + }
  14 + add_action('init', 'my_registered_post_meta_item');
  15 +
  16 +## Prettifying Your Post Meta
  17 +
  18 +By default the post meta is run through `print_r` (if its an object or array) and then through `htmlspecialchars`. Register a callback function along with your post meta key to override the default display of your post meta in the revision screen.
  19 +
  20 + function my_registered_post_meta_item() {
  21 + if (function_exists('cfr_register_metadata')) {
  22 + cfr_register_metadata('my_metadata_key', 'prettify_my_postmeta');
  23 + }
  24 + }
  25 + add_action('init', 'my_registered_post_meta_item');
  26 +
  27 + function prettify_my_postmeta($postmeta) {
  28 + // make the post meta data presentable
  29 +
  30 + return $postmeta;
  31 + }
170 cf-revision-manager.php
... ... @@ -0,0 +1,170 @@
  1 +<?php
  2 +/*
  3 +Plugin Name: CF Revision Manager
  4 +Plugin URI: http://crowdfavorite.com
  5 +Description: Revision management functionality so that plugins can add metadata to revisions as well as restore that metadata from revisions
  6 +Version: 0.1
  7 +Author: Crowd Favorite
  8 +Author URI: http://crowdfavorite.com
  9 +*/
  10 +
  11 +define('CF_REVISIONS_DEBUG', true);
  12 +
  13 +function cfr_register_metadata($postmeta_key, $display_func = '') {
  14 + static $cfr;
  15 + if (empty($cfr)) {
  16 + $cfr = cf_revisions::get_instance();
  17 + }
  18 + return $cfr->register($postmeta_key, $display_func);
  19 +}
  20 +
  21 +class cf_revisions {
  22 + private static $_instance;
  23 + protected $postmeta_keys = array();
  24 +
  25 + public function __construct() {
  26 + if (is_admin()) {
  27 + # save & restore
  28 + add_action('save_post', array($this, 'save_post_revision'), 10, 2);
  29 + add_action('wp_restore_post_revision', array($this, 'restore_post_revision'), 10, 2);
  30 +
  31 + # revision display
  32 + global $pagenow;
  33 + if ($pagenow == 'revision.php') {
  34 + add_filter('_wp_post_revision_fields', array($this, 'post_revision_fields'), 10, 1);
  35 + add_filter('_wp_post_revision_field_postmeta', array($this, 'post_revision_field'), 1, 2);
  36 + }
  37 + }
  38 + }
  39 +
  40 + public function register($postmeta_key, $display_func = '') {
  41 + if (!in_array($postmeta_key, $this->postmeta_keys, true)) {
  42 + $this->postmeta_keys[] = compact('postmeta_key', 'display_func');
  43 + }
  44 + return true;
  45 + }
  46 +
  47 + /**
  48 + * This is a paranoid check. There will be no object to register the
  49 + * actions and filters if nobody adds any postmeta to be handled
  50 + *
  51 + * @return bool
  52 + */
  53 + public function have_keys() {
  54 + return (bool) count($this->postmeta_keys);
  55 + }
  56 +
  57 + /**
  58 + * Save the revision data
  59 + *
  60 + * @param int $post_id
  61 + * @param object $post
  62 + * @return void
  63 + */
  64 + public function save_post_revision($post_id, $post) {
  65 + if ($post->post_type != 'revision' || !$this->have_keys()) {
  66 + return false;
  67 + }
  68 +
  69 + foreach ($this->postmeta_keys as $postmeta_type) {
  70 + $postmeta_key = $postmeta_type['postmeta_key'];
  71 +
  72 + if ($postmeta_value = get_post_meta($post->post_parent, $postmeta_key, true)) {
  73 + add_metadata('post', $post_id, $postmeta_key, $postmeta_value);
  74 + $this->log('Added postmeta for: '.$postmeta_key.' to revision: '.$post_id.' from post: '.$post->post_parent);
  75 + }
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * Revert the revision data
  81 + *
  82 + * @param int $post_id
  83 + * @param int $revision_id
  84 + * @return void
  85 + */
  86 + public function restore_post_revision($post_id, $revision_id) {
  87 + if (!$this->have_keys()) {
  88 + return false;
  89 + }
  90 +
  91 + foreach ($this->postmeta_keys as $postmeta_type) {
  92 + $postmeta_key = $postmeta_type['postmeta_key'];
  93 +
  94 + if ($postmeta_value = get_metadata('post', $revision_id, $postmeta_key, true)) {
  95 + if (get_metadata('post', $post_id, $postmeta_key, true)) {
  96 + $this->log('Updating postmeta: '.$postmeta_key.' for post: '.$post_id.' from revision: '.$revision_id);
  97 + update_metadata('post', $post_id, $postmeta_key, $postmeta_value);
  98 + }
  99 + else {
  100 + $this->log('Adding postmeta: '.$postmeta_key.' for post: '.$post_id);
  101 + add_metadata('post', $post_id, $postmeta_key, $postmeta_value.' from revision: '.$revision_id);
  102 + }
  103 + $this->log('Restored post_id: '.$post_id.' metadata from: '.$postmeta_key);
  104 + }
  105 + }
  106 + }
  107 +
  108 + public function post_revision_fields($fields) {
  109 + $fields['postmeta'] = 'Post Meta';
  110 + return $fields;
  111 + }
  112 +
  113 + public function post_revision_field($field_id, $field) {
  114 + if ($field != 'postmeta' || !$this->have_keys()) {
  115 + return;
  116 + }
  117 +
  118 + remove_filter('_wp_post_revision_field_postmeta', 'htmlspecialchars', 10, 2);
  119 +
  120 + $html = '<ul style="white-space: normal; margin-left: 1.5em; list-style: disc outside;">';
  121 + foreach ($this->postmeta_keys as $postmeta_type) {
  122 + $postmeta_key = $postmeta_type['postmeta_key'];
  123 + $postmeta = maybe_unserialize(get_metadata('post', intval($_GET['revision']), $postmeta_key, true));
  124 +
  125 + if (!empty($postmeta)) {
  126 + if (!empty($postmeta_type['display_func']) && function_exists($postmeta_type['display_func'])) {
  127 + $postmeta_html = $postmeta_type['display_func']($postmeta);
  128 + }
  129 + else {
  130 + $postmeta_rendered = (is_array($postmeta) || is_object($postmeta) ? print_r($postmeta, true) : $postmeta);
  131 + $postmeta_html = apply_filters('_wp_post_revision_field_postmeta_display', htmlspecialchars($postmeta_rendered), $postmeta_key, $postmeta);
  132 + }
  133 + }
  134 + else {
  135 + $postmeta_html = '*empty postmeta value*';
  136 + }
  137 +
  138 + $html .= '
  139 + <li>
  140 + <h3><a href="#postmeta-'.$postmeta_key.'" onclick="jQuery(\'#postmeta-'.$postmeta_key.'\').slideToggle(); return false;">'.$postmeta_key.'</a></h3>
  141 + <div id="postmeta-'.$postmeta_key.'" style="display: none;">'.$postmeta_html.'</div>
  142 + </li>
  143 + ';
  144 + }
  145 + $html .= '</ul>';
  146 +
  147 + return $html;
  148 + }
  149 +
  150 + /**
  151 + * Singleton
  152 + *
  153 + * @return object
  154 + */
  155 + public function get_instance() {
  156 + if (!(self::$_instance instanceof cf_revisions)) {
  157 + self::$_instance = new cf_revisions;
  158 + }
  159 + return self::$_instance;
  160 + }
  161 +
  162 + protected function log($message) {
  163 + if (CF_REVISIONS_DEBUG) {
  164 + error_log($message);
  165 + }
  166 + }
  167 +}
  168 +
  169 +#include('tests.php');
  170 +?>
181 notes/save_post.txt
... ... @@ -0,0 +1,181 @@
  1 +# Upload Attachment
  2 +
  3 +- media-upload.php
  4 + - if ( $_POST['html-upload'] )
  5 + - media_handle_upload()
  6 + - get time from parent post
  7 + - wp_handle_upload
  8 + - apply_filters( wp_handle_upload_prefilter )
  9 + - test form name parity
  10 + - test upload errors from PHP
  11 + - test file size limiations
  12 + - test file properly uploaded to temp location
  13 + - check file mime type
  14 + - wp_check_filetype_and_ext
  15 + - check user permissions on file type upload
  16 + - current_user_can
  17 + - check valid uploads dir
  18 + - wp_upload_dir
  19 + - setup uploads path
  20 + - setup uploads url
  21 + - jingle jangle for multisite
  22 + - if ( get_option( uploads_use_yearmonth_folders ) )
  23 + - if time not supplied, get time *** PLEASE NOTE ***
  24 + - build upload dir path based on time
  25 + - apply_filters ( upload_dir )
  26 + - wp_mkdir_p
  27 + - try to make target location
  28 + - return uploads dir path
  29 + - wp_unique_filename
  30 + - sanitize_title
  31 + - if ( name not unique )
  32 + - increment number until unique name is arrived at
  33 + - move file in to uploads dir
  34 + - if ( multisite )
  35 + delete_transient ( dirsize_cache )
  36 + apply_filters ( wp_handle_upload )
  37 + - wp_insert_attachment
  38 + - wp_parse_args
  39 + - sanitize_post
  40 + - set item category
  41 + - sanitize_title
  42 + - wp_unique_post_slug
  43 + - set post time & modified
  44 + - set comment status, parent, author, etc...
  45 + - stripslashes_deep
  46 + - if ( update )
  47 + - wpdb->update
  48 + - else
  49 + - try to use suggested id (import functionality)
  50 + - wpdb->insert
  51 + - set title if not already set
  52 + - wp_set_post_categories
  53 + - update_attached_file
  54 + - clean_post_cache
  55 + - if ( no parent )
  56 + - add_post_meta ( _wp_attachment_temp_parent )
  57 + - if ( update )
  58 + do_action ( edit_attachment )
  59 + - else
  60 + do_action ( add_attachment )
  61 + - if ( no error )
  62 + - wp_update_attachment_metadata ( wp_generate_attachment_metadata )
  63 + - id ( $_GET['upload-page-form'] )
  64 + - media_upload_form_handler @see #Edit Attachment for rabbit hole
  65 + - show upload form
  66 +
  67 +# Edit Attachment
  68 +
  69 +- media.php: action=editattachment
  70 + - check_admin_referer
  71 + - current_user_can
  72 + - die on invalid permissions
  73 + - media_upload_form_handler
  74 + - check_admin_referer
  75 + - get $send_id if present
  76 + - fill attachment data from $_POST
  77 + - apply_filters ( attachment_fields_to_save )
  78 + - check for image alt-text
  79 + - update alt-text
  80 + - update_post_meta ( _wp_attachment_image_alt )
  81 + - wp_update_post
  82 + - foreach ( get_attachment_taxonomies )
  83 + - wp_set_object_terms
  84 + - if ( insert_gallery )
  85 + - output gallery update js
  86 + - if ( $send_id )
  87 + - stripslashes_deep ( $_POST['attachments'][$send_id] )
  88 + - build link to return to editor
  89 + - apply_filters ( media_send_to_editor )
  90 + - return media_send_to_editor ( $html )
  91 + - determine redirect url & error messages
  92 + - wp_get_original_referer
  93 + - wp_redirect
  94 +
  95 +# Save Post
  96 +
  97 +- post.php: action=editpost
  98 + - check_admin_referer
  99 + - edit_post
  100 + - get_post_type_object
  101 + - current_user_can
  102 + - die on invalid permissions
  103 + - if ( autosave )
  104 + - get_post
  105 + - check last update
  106 + - return if too soon
  107 + - _wp_translate_postdata
  108 + - handle visibility
  109 + - iterate over $post_data['meta']
  110 + - update_meta
  111 + - iterate over $post_data['deletemeta']
  112 + - delete_meta
  113 + - add_meta
  114 + - update_post_meta
  115 + - wp_update_post
  116 + - wp_get_single_post
  117 + - add_magic_quotes
  118 + - if ( is attachment )
  119 + - wp_insert_attachment
  120 + - else
  121 + - wp_insert_post
  122 + - wp_parse_args
  123 + - sanitize_post
  124 + - get_post_field (post_status)
  125 + - assign default category if none provided
  126 + - if (update)
  127 + - get existing post state
  128 + - sanitize_title
  129 + - set post time
  130 + - set comment satus
  131 + - make sure post is not its own parent
  132 + - wp_unique_post_slug
  133 + - apply_filters ( wp_insert_post_data )
  134 + - stripslashes_deep ( postdata )
  135 + - if (update)
  136 + - do_action ( pre_post_update )
  137 + - triggers
  138 + - wp_save_post_revision
  139 + - check for existing post
  140 + - check for revision support
  141 + - _wp_put_post_revision
  142 + - _wp_post_revision_fields
  143 + - apply_filters ( _wp_post_revision_fields )
  144 + - add_magic_quotes
  145 + - wp_insert_post
  146 + - do_action _wp_put_post_revision
  147 + - wp_get_post_revisions ( post_id )
  148 + - prune out of date revisions
  149 + - wpdb->update
  150 + - else
  151 + - check for existing id, use it if available (part of import process)
  152 + - wpdb->insert
  153 + - wpdb->update - update post_name for just inserted/updated post
  154 + - if (is_object_in_taxonomy ( category ))
  155 + - wp_set_post_categories
  156 + - if ( isset (tags_input) && is_object_in_taxonomy ( post_tag ))
  157 + - wp_set_post_tags
  158 + - handle custom taxonomies
  159 + - get_taxonomy
  160 + - wp_set_post_terms
  161 + - get post guid
  162 + - clean_page_/post_cache
  163 + - wpdb->update ( post_guid )
  164 + - get_post
  165 + - check valid page template
  166 + - get_page_templates
  167 + - update_post_meta ( _wp_page_template )
  168 + - wp_transition_post_status
  169 + - if ( update )
  170 + - do_action( edit_post )
  171 + - do_action( post_updated )
  172 + - do_action ( save_post )
  173 + - do_action ( wp_insert_post )
  174 + - return
  175 + - _relocate_children
  176 + - _fix_attachment_links
  177 + - wp_set_post_lock
  178 + - stick_/unstick_post
  179 + - return
  180 + - redirect_post
  181 + - exit
37 tests.php
... ... @@ -0,0 +1,37 @@
  1 +<?php
  2 +
  3 + function cf_revisions_post_meta_config($config) {
  4 + $config[] = array(
  5 + 'title' => 'Block title', // required, Title of the Meta Box
  6 + 'description' => 'Block Description', // optional, Description text that appears at the top of the Meta Box
  7 + 'type' => array('page'), // required, Which edit screen to add to. Use array('page','post') to add to both at the same time
  8 + 'id' => 'cf-revisions-post-meta-test', // required, unique id for the Meta Box
  9 + 'add_to_sortables' => true, // optional, this is the default behavior
  10 + 'context' => 'normal', // optional, sets the location of the metabox in the edit page. Other posibilites are 'advanced' or 'side' (this sets the meta box to apear in the rt sidebar of the edit page)
  11 + 'items' => array(
  12 + // text input
  13 + array(
  14 + 'name' => '_cf_revisions_text_meta', // required, this is the meta_key that will be saved by WordPress
  15 + 'label' => 'Label Text', // optional, label only printed if text is not empty
  16 + 'label_position' => 'before', // optional, label position in relation to the input, default: 'before'
  17 + 'type' => 'text', // required, input type
  18 + 'before' => '<div class="special">', // optional, html to put before the field
  19 + 'after' => '</div>', // optional, html to put after the field
  20 + )
  21 + )
  22 + );
  23 + return $config;
  24 + }
  25 +
  26 + function cf_revisions_tests_init() {
  27 + if (function_exists('cf_meta_get_type')) {
  28 + add_filter('cf_meta_config', 'cf_revisions_post_meta_config');
  29 + cfr_register_metadata('_cf_revisions_text_meta');
  30 + }
  31 + if (function_exists('cfct_build')) {
  32 + cfr_register_metadata(CFCT_BUILD_POSTMETA, 'cfct_describe_postmeta');
  33 + }
  34 + }
  35 + add_action('init', 'cf_revisions_tests_init');
  36 +
  37 +?>

0 comments on commit 58a354d

Please sign in to comment.
Something went wrong with that request. Please try again.