Permalink
Browse files

adding proper svn structure

  • Loading branch information...
0 parents commit 58a354d45839a22337aefa0cf242a062887d80de sparker committed Sep 15, 2010
Showing with 419 additions and 0 deletions.
  1. +31 −0 README.txt
  2. +170 −0 cf-revision-manager.php
  3. +181 −0 notes/save_post.txt
  4. +37 −0 tests.php
31 README.txt
@@ -0,0 +1,31 @@
+# CF Revision Manager
+
+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.
+
+## Registering Your Post Meta
+
+The CFR plugin includes a registration function to easily include your post-meta in the revision scheme.
+
+ function my_registered_post_meta_item() {
+ if (function_exists('cfr_register_metadata')) {
+ cfr_register_metadata('my_metadata_key');
+ }
+ }
+ add_action('init', 'my_registered_post_meta_item');
+
+## Prettifying Your Post Meta
+
+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.
+
+ function my_registered_post_meta_item() {
+ if (function_exists('cfr_register_metadata')) {
+ cfr_register_metadata('my_metadata_key', 'prettify_my_postmeta');
+ }
+ }
+ add_action('init', 'my_registered_post_meta_item');
+
+ function prettify_my_postmeta($postmeta) {
+ // make the post meta data presentable
+
+ return $postmeta;
+ }
170 cf-revision-manager.php
@@ -0,0 +1,170 @@
+<?php
+/*
+Plugin Name: CF Revision Manager
+Plugin URI: http://crowdfavorite.com
+Description: Revision management functionality so that plugins can add metadata to revisions as well as restore that metadata from revisions
+Version: 0.1
+Author: Crowd Favorite
+Author URI: http://crowdfavorite.com
+*/
+
+define('CF_REVISIONS_DEBUG', true);
+
+function cfr_register_metadata($postmeta_key, $display_func = '') {
+ static $cfr;
+ if (empty($cfr)) {
+ $cfr = cf_revisions::get_instance();
+ }
+ return $cfr->register($postmeta_key, $display_func);
+}
+
+class cf_revisions {
+ private static $_instance;
+ protected $postmeta_keys = array();
+
+ public function __construct() {
+ if (is_admin()) {
+ # save & restore
+ add_action('save_post', array($this, 'save_post_revision'), 10, 2);
+ add_action('wp_restore_post_revision', array($this, 'restore_post_revision'), 10, 2);
+
+ # revision display
+ global $pagenow;
+ if ($pagenow == 'revision.php') {
+ add_filter('_wp_post_revision_fields', array($this, 'post_revision_fields'), 10, 1);
+ add_filter('_wp_post_revision_field_postmeta', array($this, 'post_revision_field'), 1, 2);
+ }
+ }
+ }
+
+ public function register($postmeta_key, $display_func = '') {
+ if (!in_array($postmeta_key, $this->postmeta_keys, true)) {
+ $this->postmeta_keys[] = compact('postmeta_key', 'display_func');
+ }
+ return true;
+ }
+
+ /**
+ * This is a paranoid check. There will be no object to register the
+ * actions and filters if nobody adds any postmeta to be handled
+ *
+ * @return bool
+ */
+ public function have_keys() {
+ return (bool) count($this->postmeta_keys);
+ }
+
+ /**
+ * Save the revision data
+ *
+ * @param int $post_id
+ * @param object $post
+ * @return void
+ */
+ public function save_post_revision($post_id, $post) {
+ if ($post->post_type != 'revision' || !$this->have_keys()) {
+ return false;
+ }
+
+ foreach ($this->postmeta_keys as $postmeta_type) {
+ $postmeta_key = $postmeta_type['postmeta_key'];
+
+ if ($postmeta_value = get_post_meta($post->post_parent, $postmeta_key, true)) {
+ add_metadata('post', $post_id, $postmeta_key, $postmeta_value);
+ $this->log('Added postmeta for: '.$postmeta_key.' to revision: '.$post_id.' from post: '.$post->post_parent);
+ }
+ }
+ }
+
+ /**
+ * Revert the revision data
+ *
+ * @param int $post_id
+ * @param int $revision_id
+ * @return void
+ */
+ public function restore_post_revision($post_id, $revision_id) {
+ if (!$this->have_keys()) {
+ return false;
+ }
+
+ foreach ($this->postmeta_keys as $postmeta_type) {
+ $postmeta_key = $postmeta_type['postmeta_key'];
+
+ if ($postmeta_value = get_metadata('post', $revision_id, $postmeta_key, true)) {
+ if (get_metadata('post', $post_id, $postmeta_key, true)) {
+ $this->log('Updating postmeta: '.$postmeta_key.' for post: '.$post_id.' from revision: '.$revision_id);
+ update_metadata('post', $post_id, $postmeta_key, $postmeta_value);
+ }
+ else {
+ $this->log('Adding postmeta: '.$postmeta_key.' for post: '.$post_id);
+ add_metadata('post', $post_id, $postmeta_key, $postmeta_value.' from revision: '.$revision_id);
+ }
+ $this->log('Restored post_id: '.$post_id.' metadata from: '.$postmeta_key);
+ }
+ }
+ }
+
+ public function post_revision_fields($fields) {
+ $fields['postmeta'] = 'Post Meta';
+ return $fields;
+ }
+
+ public function post_revision_field($field_id, $field) {
+ if ($field != 'postmeta' || !$this->have_keys()) {
+ return;
+ }
+
+ remove_filter('_wp_post_revision_field_postmeta', 'htmlspecialchars', 10, 2);
+
+ $html = '<ul style="white-space: normal; margin-left: 1.5em; list-style: disc outside;">';
+ foreach ($this->postmeta_keys as $postmeta_type) {
+ $postmeta_key = $postmeta_type['postmeta_key'];
+ $postmeta = maybe_unserialize(get_metadata('post', intval($_GET['revision']), $postmeta_key, true));
+
+ if (!empty($postmeta)) {
+ if (!empty($postmeta_type['display_func']) && function_exists($postmeta_type['display_func'])) {
+ $postmeta_html = $postmeta_type['display_func']($postmeta);
+ }
+ else {
+ $postmeta_rendered = (is_array($postmeta) || is_object($postmeta) ? print_r($postmeta, true) : $postmeta);
+ $postmeta_html = apply_filters('_wp_post_revision_field_postmeta_display', htmlspecialchars($postmeta_rendered), $postmeta_key, $postmeta);
+ }
+ }
+ else {
+ $postmeta_html = '*empty postmeta value*';
+ }
+
+ $html .= '
+ <li>
+ <h3><a href="#postmeta-'.$postmeta_key.'" onclick="jQuery(\'#postmeta-'.$postmeta_key.'\').slideToggle(); return false;">'.$postmeta_key.'</a></h3>
+ <div id="postmeta-'.$postmeta_key.'" style="display: none;">'.$postmeta_html.'</div>
+ </li>
+ ';
+ }
+ $html .= '</ul>';
+
+ return $html;
+ }
+
+ /**
+ * Singleton
+ *
+ * @return object
+ */
+ public function get_instance() {
+ if (!(self::$_instance instanceof cf_revisions)) {
+ self::$_instance = new cf_revisions;
+ }
+ return self::$_instance;
+ }
+
+ protected function log($message) {
+ if (CF_REVISIONS_DEBUG) {
+ error_log($message);
+ }
+ }
+}
+
+#include('tests.php');
+?>
181 notes/save_post.txt
@@ -0,0 +1,181 @@
+# Upload Attachment
+
+- media-upload.php
+ - if ( $_POST['html-upload'] )
+ - media_handle_upload()
+ - get time from parent post
+ - wp_handle_upload
+ - apply_filters( wp_handle_upload_prefilter )
+ - test form name parity
+ - test upload errors from PHP
+ - test file size limiations
+ - test file properly uploaded to temp location
+ - check file mime type
+ - wp_check_filetype_and_ext
+ - check user permissions on file type upload
+ - current_user_can
+ - check valid uploads dir
+ - wp_upload_dir
+ - setup uploads path
+ - setup uploads url
+ - jingle jangle for multisite
+ - if ( get_option( uploads_use_yearmonth_folders ) )
+ - if time not supplied, get time *** PLEASE NOTE ***
+ - build upload dir path based on time
+ - apply_filters ( upload_dir )
+ - wp_mkdir_p
+ - try to make target location
+ - return uploads dir path
+ - wp_unique_filename
+ - sanitize_title
+ - if ( name not unique )
+ - increment number until unique name is arrived at
+ - move file in to uploads dir
+ - if ( multisite )
+ delete_transient ( dirsize_cache )
+ apply_filters ( wp_handle_upload )
+ - wp_insert_attachment
+ - wp_parse_args
+ - sanitize_post
+ - set item category
+ - sanitize_title
+ - wp_unique_post_slug
+ - set post time & modified
+ - set comment status, parent, author, etc...
+ - stripslashes_deep
+ - if ( update )
+ - wpdb->update
+ - else
+ - try to use suggested id (import functionality)
+ - wpdb->insert
+ - set title if not already set
+ - wp_set_post_categories
+ - update_attached_file
+ - clean_post_cache
+ - if ( no parent )
+ - add_post_meta ( _wp_attachment_temp_parent )
+ - if ( update )
+ do_action ( edit_attachment )
+ - else
+ do_action ( add_attachment )
+ - if ( no error )
+ - wp_update_attachment_metadata ( wp_generate_attachment_metadata )
+ - id ( $_GET['upload-page-form'] )
+ - media_upload_form_handler @see #Edit Attachment for rabbit hole
+ - show upload form
+
+# Edit Attachment
+
+- media.php: action=editattachment
+ - check_admin_referer
+ - current_user_can
+ - die on invalid permissions
+ - media_upload_form_handler
+ - check_admin_referer
+ - get $send_id if present
+ - fill attachment data from $_POST
+ - apply_filters ( attachment_fields_to_save )
+ - check for image alt-text
+ - update alt-text
+ - update_post_meta ( _wp_attachment_image_alt )
+ - wp_update_post
+ - foreach ( get_attachment_taxonomies )
+ - wp_set_object_terms
+ - if ( insert_gallery )
+ - output gallery update js
+ - if ( $send_id )
+ - stripslashes_deep ( $_POST['attachments'][$send_id] )
+ - build link to return to editor
+ - apply_filters ( media_send_to_editor )
+ - return media_send_to_editor ( $html )
+ - determine redirect url & error messages
+ - wp_get_original_referer
+ - wp_redirect
+
+# Save Post
+
+- post.php: action=editpost
+ - check_admin_referer
+ - edit_post
+ - get_post_type_object
+ - current_user_can
+ - die on invalid permissions
+ - if ( autosave )
+ - get_post
+ - check last update
+ - return if too soon
+ - _wp_translate_postdata
+ - handle visibility
+ - iterate over $post_data['meta']
+ - update_meta
+ - iterate over $post_data['deletemeta']
+ - delete_meta
+ - add_meta
+ - update_post_meta
+ - wp_update_post
+ - wp_get_single_post
+ - add_magic_quotes
+ - if ( is attachment )
+ - wp_insert_attachment
+ - else
+ - wp_insert_post
+ - wp_parse_args
+ - sanitize_post
+ - get_post_field (post_status)
+ - assign default category if none provided
+ - if (update)
+ - get existing post state
+ - sanitize_title
+ - set post time
+ - set comment satus
+ - make sure post is not its own parent
+ - wp_unique_post_slug
+ - apply_filters ( wp_insert_post_data )
+ - stripslashes_deep ( postdata )
+ - if (update)
+ - do_action ( pre_post_update )
+ - triggers
+ - wp_save_post_revision
+ - check for existing post
+ - check for revision support
+ - _wp_put_post_revision
+ - _wp_post_revision_fields
+ - apply_filters ( _wp_post_revision_fields )
+ - add_magic_quotes
+ - wp_insert_post
+ - do_action _wp_put_post_revision
+ - wp_get_post_revisions ( post_id )
+ - prune out of date revisions
+ - wpdb->update
+ - else
+ - check for existing id, use it if available (part of import process)
+ - wpdb->insert
+ - wpdb->update - update post_name for just inserted/updated post
+ - if (is_object_in_taxonomy ( category ))
+ - wp_set_post_categories
+ - if ( isset (tags_input) && is_object_in_taxonomy ( post_tag ))
+ - wp_set_post_tags
+ - handle custom taxonomies
+ - get_taxonomy
+ - wp_set_post_terms
+ - get post guid
+ - clean_page_/post_cache
+ - wpdb->update ( post_guid )
+ - get_post
+ - check valid page template
+ - get_page_templates
+ - update_post_meta ( _wp_page_template )
+ - wp_transition_post_status
+ - if ( update )
+ - do_action( edit_post )
+ - do_action( post_updated )
+ - do_action ( save_post )
+ - do_action ( wp_insert_post )
+ - return
+ - _relocate_children
+ - _fix_attachment_links
+ - wp_set_post_lock
+ - stick_/unstick_post
+ - return
+ - redirect_post
+ - exit
37 tests.php
@@ -0,0 +1,37 @@
+<?php
+
+ function cf_revisions_post_meta_config($config) {
+ $config[] = array(
+ 'title' => 'Block title', // required, Title of the Meta Box
+ 'description' => 'Block Description', // optional, Description text that appears at the top of the Meta Box
+ 'type' => array('page'), // required, Which edit screen to add to. Use array('page','post') to add to both at the same time
+ 'id' => 'cf-revisions-post-meta-test', // required, unique id for the Meta Box
+ 'add_to_sortables' => true, // optional, this is the default behavior
+ '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)
+ 'items' => array(
+ // text input
+ array(
+ 'name' => '_cf_revisions_text_meta', // required, this is the meta_key that will be saved by WordPress
+ 'label' => 'Label Text', // optional, label only printed if text is not empty
+ 'label_position' => 'before', // optional, label position in relation to the input, default: 'before'
+ 'type' => 'text', // required, input type
+ 'before' => '<div class="special">', // optional, html to put before the field
+ 'after' => '</div>', // optional, html to put after the field
+ )
+ )
+ );
+ return $config;
+ }
+
+ function cf_revisions_tests_init() {
+ if (function_exists('cf_meta_get_type')) {
+ add_filter('cf_meta_config', 'cf_revisions_post_meta_config');
+ cfr_register_metadata('_cf_revisions_text_meta');
+ }
+ if (function_exists('cfct_build')) {
+ cfr_register_metadata(CFCT_BUILD_POSTMETA, 'cfct_describe_postmeta');
+ }
+ }
+ add_action('init', 'cf_revisions_tests_init');
+
+?>

0 comments on commit 58a354d

Please sign in to comment.