├── lang
├── raph-it_IT.mo
└── raph-it_IT.po
├── .gitignore
├── composer.json
├── LICENSE
├── src
├── PostProvider.php
├── AdminForm.php
├── Renderer.php
└── FormData.php
├── README.md
├── Raph.php
└── js
├── raph.min.js
└── raph.js
/lang/raph-it_IT.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gmazzap/Raph/HEAD/lang/raph-it_IT.mo
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Thumbs.db
2 | ehthumbs.db
3 | Desktop.ini
4 | $RECYCLE.BIN/
5 | .DS_Store
6 | .coverage
7 | .tox
8 | .idea/
9 | vendor/
10 | composer.lock
11 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gmazzap/raph",
3 | "description": "WordPress plugin that renders shortcodes in posts content.",
4 | "keywords": [
5 | "wordpress"
6 | ],
7 | "type": "wordpress-plugin",
8 | "authors": [
9 | {
10 | "name": "Giuseppe Mazzapica",
11 | "email": "giuseppe.mazzapica@gmail.com",
12 | "homepage": "http://gm.zoomlab.it",
13 | "role": "Developer"
14 | }
15 | ],
16 | "support": {
17 | "issues": "https://github.com/Giuseppe-Mazzapica/Raph/issues",
18 | "source": "https://github.com/Giuseppe-Mazzapica/Raph"
19 | },
20 | "license": "MIT",
21 | "require": {
22 | "php": ">=5.4"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "Raph\\": "src/"
27 | }
28 | },
29 | "minimum-stability": "dev",
30 | "prefer-stable": true,
31 | "config": {
32 | "optimize-autoloader": true
33 | },
34 | "extra": {
35 | "branch-alias": {
36 | "dev-master": "0.3.x-dev"
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Giuseppe Mazzapica
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/PostProvider.php:
--------------------------------------------------------------------------------
1 |
4 | * @license http://opensource.org/licenses/MIT MIT
5 | */
6 | namespace Raph;
7 |
8 | use WP_Post;
9 |
10 | /**
11 | * Handle post object recognition on post editing admin screen.
12 | *
13 | * @package Raph
14 | */
15 | class PostProvider
16 | {
17 | /**
18 | * @var WP_Post
19 | */
20 | private $post;
21 |
22 | /**
23 | * Run on 'admin_init' and get current post object information form request (for existing post)
24 | * or from 'new_to_auto-draft' hoof for new posts.
25 | *
26 | * @return PostProvider
27 | */
28 | public function init()
29 | {
30 | $this->fromRequest() or $this->onTransition();
31 |
32 | return $this;
33 | }
34 |
35 | /**
36 | * @return WP_Post
37 | */
38 | public function get()
39 | {
40 | return $this->post;
41 | }
42 |
43 | private function fromRequest()
44 | {
45 | if (is_null($this->post)) {
46 | $p_get = filter_input(INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT);
47 | $p_post = filter_input(INPUT_POST, 'post', FILTER_SANITIZE_NUMBER_INT);
48 | if ($p_get > 0 || $p_post > 0) {
49 | $this->post = $p_get > 0 ? get_post($p_get) : get_post($p_post);
50 | }
51 | }
52 |
53 | return $this->post instanceof WP_Post;
54 | }
55 |
56 | private function onTransition()
57 | {
58 | if ($GLOBALS['pagenow'] === 'post-new.php' && is_null($this->post)) {
59 | add_action('new_to_auto-draft', function (WP_Post $post) {
60 | $this->post = $post;
61 | }, 0);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/AdminForm.php:
--------------------------------------------------------------------------------
1 |
4 | * @license http://opensource.org/licenses/MIT MIT
5 | */
6 | namespace Raph;
7 |
8 | /**
9 | * Adds plugin scripts and scripts data.
10 | *
11 | * @package Raph
12 | */
13 | class AdminForm
14 | {
15 | /**
16 | * @var \Raph\FormData
17 | */
18 | private $formData;
19 |
20 | /**
21 | * @param \Raph\FormData $formData
22 | */
23 | public function __construct(FormData $formData)
24 | {
25 | $this->formData = $formData;
26 | }
27 |
28 | /**
29 | * Adds Raph button to TinyMCE toolbar and connect it with javascript file.
30 | * Runs on 'admin_init' hook (se in main plugin file).
31 | */
32 | public function setup()
33 | {
34 | add_action('admin_head', function () {
35 | echo "
36 |
40 | ";
41 | });
42 | add_action('admin_enqueue_scripts', function () {
43 | wp_localize_script('editor', 'Raph', $this->formData->data());
44 | });
45 | add_filter('mce_buttons', function (array $buttons) {
46 | return array_merge($buttons, ['raphRender']);
47 | });
48 | add_filter('mce_external_plugins', function (array $plugins) {
49 | return array_merge($plugins, ['raphRender' => $this->scriptUrl()]);
50 | });
51 | }
52 |
53 | private function scriptUrl()
54 | {
55 | $name = defined('WP_DEBUG') && WP_DEBUG ? "/js/raph.js" : "/js/raph.min.js";
56 |
57 | return plugins_url($name, dirname(__DIR__).'/Raph.php');
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lang/raph-it_IT.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: Raph v0.1\n"
4 | "Report-Msgid-Bugs-To: \n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: 2015-02-01 06:59:12+0000\n"
7 | "Last-Translator: admin \n"
8 | "Language-Team: \n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Plural-Forms: nplurals=2; plural=n != 1;\n"
13 | "X-Generator: CSL v1.x\n"
14 | "X-Poedit-Language: Italian\n"
15 | "X-Poedit-Country: ITALY\n"
16 | "X-Poedit-SourceCharset: utf-8\n"
17 | "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
18 | "X-Poedit-Basepath: \n"
19 | "X-Poedit-Bookmarks: \n"
20 | "X-Poedit-SearchPath-0: .\n"
21 | "X-Textdomain-Support: yes"
22 |
23 | #: src/FormData.php:53
24 | #@ raph
25 | msgid "Render Shortcodes"
26 | msgstr "Renderizza Shortcode"
27 |
28 | #: src/FormData.php:54
29 | #@ raph
30 | msgid "No shortcodes to render."
31 | msgstr "Nessuno shortcode da renderizzare."
32 |
33 | #: src/FormData.php:55
34 | #@ raph
35 | msgid "Restore."
36 | msgstr "Ripristina."
37 |
38 | #: src/FormData.php:57
39 | #@ raph
40 | msgid "Shortcodes rendered. Save post to make changes effective."
41 | msgstr "Shortcode renderizzati. Salva il post per rendere effettive le modifiche."
42 |
43 | #: src/FormData.php:61
44 | #@ raph
45 | msgid "Sorry, an error occurred while rendering shortcodes."
46 | msgstr "Spiacenti, si è verificato un errore."
47 |
48 | #: src/FormData.php:64
49 | #@ raph
50 | msgid "Content has changed since last rendering."
51 | msgstr "Il contenuto è cambiato dall'ultimo rendering."
52 |
53 | #: src/FormData.php:65
54 | #@ raph
55 | msgid "By restoring you will lost those changes."
56 | msgstr "Se ripristini, il contenuto modificato dopo il rendering sarà perso."
57 |
58 |
--------------------------------------------------------------------------------
/src/Renderer.php:
--------------------------------------------------------------------------------
1 |
4 | * @license http://opensource.org/licenses/MIT MIT
5 | */
6 | namespace Raph;
7 |
8 | /**
9 | * Used to render post shortcodes via AJAX.
10 | *
11 | * @package Raph
12 | */
13 | class Renderer
14 | {
15 | /**
16 | * @var \Raph\FormData
17 | */
18 | private $formData;
19 |
20 | /**
21 | * @param \Raph\FormData $formData
22 | */
23 | public function __construct(FormData $formData)
24 | {
25 | $this->formData = $formData;
26 | }
27 |
28 | /**
29 | * Does security checks then takes content from AJAX POST data and send back rendered content
30 | * as JSON. Runs on 'wp_ajax_raph-render' action (set in main plugin file).
31 | */
32 | public function render()
33 | {
34 | if (defined('DOING_AJAX') && DOING_AJAX) {
35 | $check = $this->formData->check();
36 | $check or wp_send_json_error();
37 | $this->buildContext($check);
38 | $data = [
39 | 'success' => true,
40 | 'data' => ['content' => do_shortcode($check['content'])],
41 | ];
42 | @header('Content-Type: application/json; charset='.get_option('blog_charset'));
43 | echo wp_json_encode($data, JSON_PRETTY_PRINT);
44 | wp_die();
45 | }
46 | }
47 |
48 | private function buildContext(array $data)
49 | {
50 | global $wp, $wp_the_query, $post;
51 | $v = $data['type'] === 'page' ? 'page_id' : 'p';
52 | $wp->query_vars = [$v => $data['pid'], 'suppress_filters' => true];
53 | $wp->build_query_string();
54 | add_action('parse_query', function () {
55 | remove_all_actions('pre_get_posts');
56 | }, PHP_INT_MAX);
57 | $wp_the_query->query($wp->query_vars);
58 | $post = $wp_the_query->post;
59 | setup_postdata($post);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Raph
2 |
3 | > **WordPress plugin that helps you to covert shortcodes to HTML.**
4 |
5 | ----
6 |
7 | ## Sorry?
8 |
9 | Shortcodes may be useful, but rendering them "on the fly" can be a performance killer.
10 |
11 | Moreover, shortcodes added by themes or by plugins, lock you in with those products, because you if you change
12 | theme or uninstall plugins that add shortcodes, your content will be bungled when not lost.
13 |
14 | Have you ever desired get rid of a plugin, but can't because of shorteds? Now you can.
15 |
16 | ## How it Works
17 |
18 | Raph adds a button in in post editor toolbar. When you click that button
19 |
20 | - if *nothing is selected* all the shortcodes in the post are converted to the same HTML they would output in frontend
21 | - if *something is selected*, than only shortcodes in selection are converted
22 |
23 | HTML is generated via AJAX and isn't saved until post is saved.
24 |
25 | When post is saved, shortcodes are definitely converted to HTML, it means you can even disable the plugin (or switch the theme) that added the original shortcode.
26 |
27 | After having rendered shortcodes there is the possibility to immediately restore shortcodes by clicking a link.
28 |
29 | ----
30 |
31 | ## Demo
32 |
33 | 
34 |
35 | ----
36 |
37 | ## FAQ
38 |
39 | - ***How can I bulk convert shortcodes?***
40 |
41 | At the moment that isn't possible. *Maybe* it will be in future versions.
42 |
43 | - ***I selected a shortcode and clicked render button, but nothing happen, is it broken?***
44 |
45 | No. When you select some text, you have to keep the selection as is until rendering is complete. Otherwise Raph don't know where to put rendered HTML, and to avoid to mess up your post content it does nohing.
46 |
47 |
48 |
49 | ## Requirements
50 |
51 | - PHP 5.4+
52 | - WordPress 4.0+
53 |
54 | ----
55 |
56 | ## Installation
57 |
58 | The plugin is a Composer package and can be installed in plugin directory via:
59 |
60 | composer create-project gmazzap/raph
61 |
62 | Alternatively, you can
63 |
64 | - download [last release](https://github.com/Giuseppe-Mazzapica/Raph/releases) zip file
65 | - clone this repo using git
66 |
67 | ----
68 |
69 | ## License
70 |
71 | Raph is licensed under [MIT](http://opensource.org/licenses/MIT).
72 |
--------------------------------------------------------------------------------
/Raph.php:
--------------------------------------------------------------------------------
1 | init())), 'setup']);
59 | }
60 |
--------------------------------------------------------------------------------
/js/raph.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Part of Raph WordPress plugin
3 | * Author: Giuseppe Mazzapica
4 | * License: MIT
5 | */
6 | !function(e,n,t,o,a){"use strict";t.methods={},t.backup={},t.info={},t.methods.updateEditor=function(e){if(t.info.whileRendering)return!1;var n=t.methods.getContent(e);-1!==n.content.search(/\[.+\]/)?n.isSelection?t.methods.render(e,n.content,n.isSelection):e.windowManager.confirm(t.i18n.confAll,function(o){o&&t.methods.render(e,n.content,n.isSelection)}):t.methods.htmlNotice(t.i18n.noShortcodes,"error")},t.methods.getContent=function(e){var n,o;return e.selection.isCollapsed()?(n=e.getContent(),o=!1):(n=e.selection.getContent(),o=!0,t.info.currentSelection=n),{content:n,isSelection:o}},t.methods.render=function(n,o,a){t.methods.startRendering(n),t.methods.backup(n,n.getContent()),e("#raph-notice").length&&e("#raph-notice").remove(),t.methods.ajaxCall(o).done(function(e){t.methods.ajaxDone(e,n,a)}).fail(function(){t.methods.htmlNotice(t.i18n.ajaxError,"error"),t.backup={}}).always(function(){t.methods.endRendering(n)})},t.methods.ajaxCall=function(n){return e.ajax({type:"POST",url:o,dataType:"json",cache:!1,data:{action:"raph-render",pid:t.data.pid,type:t.data.type,raphCheck:t.data.raphCheck,content:n}})},t.methods.ajaxDone=function(e,n,o){if(e.success&&e.data.content){if(o&&n.selection.getContent()!==t.info.currentSelection)return t.backup={},!1;o?n.selection.setContent(e.data.content):n.setContent(e.data.content);var a=t.i18n.notice;a+=' '+t.i18n.restore+"",t.methods.htmlNotice(a,"updated"),n.onChange.add(function(){t.backup.editor&&(t.backup.changed=!0)})}else t.methods.htmlNotice(t.i18n.ajaxError,"error"),t.backup={}},t.methods.htmlNotice=function(n,t){e("#wp-content-wrap").prepend('"),"error"===t&&setTimeout(function(){e("#raph-notice").remove()},5e3)},t.methods.backup=function(e,n){t.backup.editor=e,t.backup.content=n,t.backup.changed=!1},t.methods.restoreContentConfirm=function(){if(t.backup.editor){var e=!t.backup.changed;e?t.methods.restoreContent():t.backup.editor.windowManager.confirm(t.i18n.conf1+"\n"+t.i18n.conf2,function(){t.methods.restoreContent()})}},t.methods.restoreContent=function(){t.backup.editor&&(t.backup.editor.setContent(t.backup.content),e("#raph-notice").remove(),t.backup={})},t.methods.startRendering=function(e){var n=e.controlManager.buttons.raphRender;n.icon("raph dashicons-clock"),n.disabled(!0),t.info.whileRendering=!0},t.methods.endRendering=function(e){var n=e.controlManager.buttons.raphRender;n.icon("raph dashicons-admin-appearance"),n.disabled(!1),t.info={}},n.PluginManager.add("raphRender",function(e){e.addButton("raphRender",{title:t.i18n.buttonTitle,icon:"raph dashicons-admin-appearance",onclick:function(){t.methods.updateEditor(e)}})}),e(a).on("click","#raph-restore",function(e){e.preventDefault(),t.methods.restoreContentConfirm()})}(jQuery,tinymce,Raph,ajaxurl,document);
--------------------------------------------------------------------------------
/src/FormData.php:
--------------------------------------------------------------------------------
1 |
4 | * @license http://opensource.org/licenses/MIT MIT
5 | */
6 | namespace Raph;
7 |
8 | use WP_Post;
9 |
10 | /**
11 | * Used by Renderer and AdminForm classes to, respectively, retrieve and set data for post
12 | * rendering.
13 | *
14 | * @package Raph
15 | */
16 | class FormData
17 | {
18 | /**
19 | * @var string
20 | */
21 | private static $nonce = 'raph_render';
22 |
23 | /**
24 | * @var \Raph\PostProvider
25 | */
26 | private $postProvider;
27 |
28 | /**
29 | * @param \Raph\PostProvider $postProvider
30 | */
31 | public function __construct(PostProvider $postProvider = null)
32 | {
33 | $this->postProvider = $postProvider;
34 | }
35 |
36 | /**
37 | * Return the data to be passed to javascript and be used to translate UI and send AJAX request.
38 | *
39 | * @return array
40 | */
41 | public function data()
42 | {
43 | $post = $this->postProvider instanceof PostProvider ? $this->postProvider->get() : null;
44 |
45 | if ($post instanceof WP_Post) {
46 | return [
47 | 'i18n' => [
48 | 'buttonTitle' => __('Render Shortcodes', 'raph'),
49 | 'noShortcodes' => __('No shortcodes to render.', 'raph'),
50 | 'restore' => __('Restore.', 'raph'),
51 | 'notice' => __(
52 | 'Shortcodes rendered. Save post to make changes effective.',
53 | 'raph'
54 | ),
55 | 'ajaxError' => __(
56 | 'Sorry, an error occurred while rendering shortcodes.',
57 | 'raph'
58 | ),
59 | 'conf1' => __('Content has changed since last rendering.', 'raph'),
60 | 'conf2' => __('By restoring you will lost those changes.', 'raph'),
61 | 'confAll' => __('Do you want to render ALL shortcodes?', 'raph'),
62 | ],
63 | 'data' => [
64 | 'pid' => absint($post->ID),
65 | 'type' => filter_var($post->post_type, FILTER_SANITIZE_STRING),
66 | 'raphCheck' => wp_create_nonce($this->nonceAction($post->ID)),
67 | ]
68 | ];
69 | }
70 | }
71 |
72 | /**
73 | * Verify that $_POST data for a post and that current user has the capability to edit the post.
74 | *
75 | * @return bool|array
76 | */
77 | public function check()
78 | {
79 | $data = filter_input_array(INPUT_POST, [
80 | 'pid' => FILTER_SANITIZE_NUMBER_INT,
81 | 'type' => FILTER_SANITIZE_STRING,
82 | 'raphCheck' => FILTER_SANITIZE_STRING,
83 | 'content' => FILTER_REQUIRE_SCALAR
84 | ]);
85 |
86 | return
87 | wp_verify_nonce($data['raphCheck'], $this->nonceAction($data['pid']))
88 | && $this->userCan($data['pid'], $data['type'])
89 | && ! empty($data['content'])
90 | ? $data
91 | : false;
92 | }
93 |
94 | private function nonceAction($id)
95 | {
96 | return self::$nonce.md5($id.LOGGED_IN_SALT.get_current_blog_id());
97 | }
98 |
99 | private function userCan($id, $type)
100 | {
101 | $postType = get_post_type_object($type);
102 |
103 | return is_object($postType) && current_user_can($postType->cap->edit_post, $id);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/js/raph.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Part of Raph WordPress plugin
3 | * Author: Giuseppe Mazzapica
4 | * License: MIT
5 | */
6 |
7 | (function ( $, T, R, ajaxurl, document ) {
8 |
9 | "use strict";
10 |
11 | R.methods = {};
12 | R.backup = {};
13 | R.info = {};
14 |
15 | /**
16 | * First function launched when Raph button is clicked.
17 | * Gets data, performs checks and launches rendering.
18 | *
19 | * @param {tinymce.Editor} editor TinyMCE Editor object
20 | */
21 | R.methods.updateEditor = function ( editor ) {
22 | if ( R.info.whileRendering ) {
23 | return false;
24 | }
25 | var get = R.methods.getContent( editor );
26 | if ( get.content.search( /\[.+\]/ ) !== -1 ) {
27 | if ( !get.isSelection ) {
28 | editor.windowManager.confirm( R.i18n.confAll, function ( confirm ) {
29 | if ( confirm ) {
30 | R.methods.render( editor, get.content, get.isSelection );
31 | }
32 | } );
33 | } else {
34 | R.methods.render( editor, get.content, get.isSelection );
35 | }
36 | } else {
37 | R.methods.htmlNotice( R.i18n.noShortcodes, 'error' );
38 | }
39 | };
40 |
41 | /**
42 | * Get content to process from editor, and check if is a selection or the whole post content.
43 | *
44 | * @param {String} editor
45 | * @returns {{content: String, isSelection: Boolean}}
46 | */
47 | R.methods.getContent = function ( editor ) {
48 | var content, isSelection;
49 | if ( !editor.selection.isCollapsed() ) {
50 | content = editor.selection.getContent();
51 | isSelection = true;
52 | R.info.currentSelection = content;
53 | } else {
54 | content = editor.getContent();
55 | isSelection = false;
56 | }
57 | return {
58 | content: content,
59 | isSelection: isSelection
60 | };
61 | };
62 |
63 | /**
64 | * Launches the AJAX call, and output a notice in both cases request was successful or not.
65 | *
66 | * @param {tinymce.Editor} editor TinyMCE Editor object
67 | * @param {String} content Current editor content
68 | * @param {Boolean} isSelection When true content is a selection
69 | */
70 | R.methods.render = function ( editor, content, isSelection ) {
71 | R.methods.startRendering( editor );
72 | R.methods.backup( editor, editor.getContent() );
73 | if ( $( '#raph-notice' ).length ) {
74 | $( '#raph-notice' ).remove();
75 | }
76 | R.methods.ajaxCall( content )
77 | .done( function ( result ) {
78 | R.methods.ajaxDone( result, editor, isSelection );
79 | } ).fail( function () {
80 | R.methods.htmlNotice( R.i18n.ajaxError, 'error' );
81 | R.backup = {};
82 | } ).always( function () {
83 | R.methods.endRendering( editor );
84 | } );
85 | };
86 |
87 | /**
88 | * Performs the AJAX request.
89 | *
90 | * @param {String} content Current shortcode content
91 | * @returns {jqXHR}
92 | */
93 | R.methods.ajaxCall = function ( content ) {
94 | return $.ajax( {
95 | type: "POST",
96 | url: ajaxurl,
97 | dataType: "json",
98 | cache: false,
99 | data: {
100 | action: 'raph-render',
101 | pid: R.data.pid,
102 | type: R.data.type,
103 | raphCheck: R.data.raphCheck,
104 | content: content
105 | }
106 | } );
107 | };
108 |
109 | /**
110 | * Runs when AJAx request was successful.
111 | * Updates editor content and print success notice.
112 | * Finally adds an event to editor to see when editor content has been changed.
113 | *
114 | * @param {Object} result JSON returned by AJAX
115 | * @param {tinymce.Editor} editor TinyMCE Editor object
116 | * @param {Boolean} selection When true content is a selection
117 | */
118 | R.methods.ajaxDone = function ( result, editor, selection ) {
119 | if ( result.success && result.data.content ) {
120 | if ( selection && editor.selection.getContent() !== R.info.currentSelection ) {
121 | R.backup = {};
122 | return false;
123 | } else if ( !selection ) {
124 | editor.setContent( result.data.content );
125 | } else {
126 | editor.selection.setContent( result.data.content );
127 | }
128 | var text = R.i18n.notice;
129 | text += ' ' + R.i18n.restore + '';
130 | R.methods.htmlNotice( text, 'updated' );
131 | editor.onChange.add( function () {
132 | if ( R.backup.editor ) {
133 | R.backup.changed = true;
134 | }
135 | } );
136 | } else {
137 | R.methods.htmlNotice( R.i18n.ajaxError, 'error' );
138 | R.backup = {};
139 | }
140 | };
141 |
142 | /**
143 | * Used to print both success and error notice.
144 | * Error notices are auto deleted via timeout.
145 | *
146 | * @param {String} text Notice text
147 | * @param {String} type Used for HTML class of the notics
148 | */
149 | R.methods.htmlNotice = function ( text, type ) {
150 | $( '#wp-content-wrap' ).prepend(
151 | ''
152 | );
153 | if ( type === 'error' ) {
154 | setTimeout( function () {
155 | $( '#raph-notice' ).remove();
156 | }, 5000 );
157 | }
158 | };
159 |
160 | /**
161 | * Stores original content and editor object to be used for restoring if required.
162 | *
163 | * @param {tinymce.Editor} editor TinyMCE Editor object
164 | * @param {String} content Content before rendering
165 | */
166 | R.methods.backup = function ( editor, content ) {
167 | R.backup.editor = editor;
168 | R.backup.content = content;
169 | R.backup.changed = false;
170 | };
171 |
172 | /**
173 | * Runs when a content restore is required by user.
174 | * If the content has changed a confirmation is required, because new content will be lost.
175 | */
176 | R.methods.restoreContentConfirm = function () {
177 | if ( R.backup.editor ) {
178 | var should = !R.backup.changed;
179 | if ( !should ) {
180 | R.backup.editor.windowManager.confirm(
181 | R.i18n.conf1 + "\n" + R.i18n.conf2,
182 | function ( confirm ) {
183 | R.methods.restoreContent();
184 | }
185 | );
186 | } else {
187 | R.methods.restoreContent();
188 | }
189 | }
190 |
191 | };
192 |
193 | /**
194 | * Actually restores editor content to how it was before rendering.
195 | */
196 | R.methods.restoreContent = function () {
197 | if ( R.backup.editor ) {
198 | R.backup.editor.setContent( R.backup.content );
199 | $( '#raph-notice' ).remove();
200 | R.backup = {};
201 | }
202 | };
203 |
204 | /**
205 | * Set flags variable, add modal and disable button when rendering starts
206 | *
207 | * @param {tinymce.Editor} editor TinyMCE Editor object
208 | */
209 | R.methods.startRendering = function ( editor ) {
210 | var button = editor.controlManager.buttons.raphRender;
211 | button.icon( 'raph dashicons-clock' );
212 | button.disabled( true );
213 | R.info.whileRendering = true;
214 | };
215 |
216 | /**
217 | * Set flags variable, remove modal and re-enable button when rendering ends
218 | *
219 | * @param {tinymce.Editor} editor TinyMCE Editor object
220 | */
221 | R.methods.endRendering = function ( editor ) {
222 | var button = editor.controlManager.buttons.raphRender;
223 | button.icon( 'raph dashicons-admin-appearance' );
224 | button.disabled( false );
225 | R.info = {};
226 | };
227 |
228 | /**
229 | * Uses TinyMCE API to add Raph custom button.
230 | */
231 | T.PluginManager.add( 'raphRender', function ( editor ) {
232 | editor.addButton( 'raphRender', {
233 | title: R.i18n.buttonTitle,
234 | icon: 'raph dashicons-admin-appearance',
235 | onclick: function () {
236 | R.methods.updateEditor( editor );
237 | }
238 | } );
239 | } );
240 |
241 | // Events
242 |
243 | $( document ).on( 'click', '#raph-restore', function ( e ) {
244 | e.preventDefault();
245 | R.methods.restoreContentConfirm();
246 | } );
247 |
248 | })( jQuery, tinymce, Raph, ajaxurl, document );
--------------------------------------------------------------------------------