Removed explicit TinyMCE support, replaced with support for arbitrary page_formats. The TinyMCE files will be removed in an upcoming commit.
authorDan Fuhry <dan@enanocms.org>
Thu, 02 Jun 2011 05:28:28 -0400
changeset 1343 2a31905a567d
parent 1342 2164d18cb10c
child 1344 dc96d6c5cd1e
Removed explicit TinyMCE support, replaced with support for arbitrary page_formats. The TinyMCE files will be removed in an upcoming commit.
ajax.php
includes/clientside/static/editor.js
includes/clientside/static/enano-lib-basic.js
includes/common.php
includes/namespaces/default.php
includes/pageprocess.php
includes/render.php
install/schemas/upgrade/mysql/1126.sql
install/schemas/upgrade/postgresql/1126.sql
language/english/core.json
--- a/ajax.php	Thu Jun 02 05:24:38 2011 -0400
+++ b/ajax.php	Thu Jun 02 05:28:28 2011 -0400
@@ -77,18 +77,10 @@
 			);
 		
 		$return['page_format'] = $page->ns->cdata['page_format'];
-		if ( $return['page_format'] == 'xhtml' )
+		$code = $plugins->setHook('get_page_source');
+		foreach ( $code as $cmd )
 		{
-			// gently process headings to make tinymce format them correctly
-			if ( preg_match_all('/^ *?(={1,6}) *(.+?) *\\1 *$/m', $return['src'], $matches) )
-			{
-				foreach ( $matches[0] as $i => $match )
-				{
-					$hi = strlen($matches[1][$i]);
-					$heading = "<h{$hi}>{$matches[2][$i]}</h{$hi}>";
-					$return['src'] = str_replace_once($match, $heading, $return['src']);
-				}
-			}
+			eval($cmd);
 		}
 		
 		if ( $have_draft )
@@ -244,32 +236,32 @@
 				else
 				{
 					$src = RenderMan::preprocess_text($request['src'], false, false);
-					$draft_format = $request['format'];
-					if ( !in_array($draft_format, array('xhtml', 'wikitext')) )
+					$draft_format = $db->escape($request['format']);
+					
+					// Save the draft
+					if ( !preg_match('/^[a-z0-9_]+$/', $draft_format) )
 					{
 						$return = array(
-							'mode' => 'error',
-							'error' => 'invalid_format'
-						);
+								'mode' => 'error',
+								'error' => 'Page format must match /^[a-z0-9_]+$/'
+							);
 					}
 					else
 					{
-						// Save the draft
 						$q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, author_uid, edit_summary, page_text, is_draft, time_id, page_format )
-												VALUES (
-													\'page\',
-													\'edit\',
-													\'' . $db->escape($paths->page_id) . '\',
-													\'' . $db->escape($paths->namespace) . '\',
-													\'' . $db->escape($session->username) . '\',
-													' . $session->user_id . ',
-													\'' . $db->escape($request['summary']) . '\',
-													\'' . $db->escape($src) . '\',
-													1,
-													' . time() . ',
-													\'' . $draft_format . '\'
-												);');
-						
+											VALUES (
+												\'page\',
+												\'edit\',
+												\'' . $db->escape($paths->page_id) . '\',
+												\'' . $db->escape($paths->namespace) . '\',
+												\'' . $db->escape($session->username) . '\',
+												' . $session->user_id . ',
+												\'' . $db->escape($request['summary']) . '\',
+												\'' . $db->escape($src) . '\',
+												1,
+												' . time() . ',
+												\'' . $draft_format . '\'
+											);');
 						// Done!
 						$return = array(
 								'mode' => 'success',
@@ -302,7 +294,7 @@
 			}
 			
 			// Verify captcha, if needed
-			if ( false && !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
+			if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
 			{
 				if ( !isset($request['captcha_id']) || !isset($request['captcha_code']) )
 				{
--- a/includes/clientside/static/editor.js	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/clientside/static/editor.js	Thu Jun 02 05:28:28 2011 -0400
@@ -8,6 +8,7 @@
 var editor_wikitext_transform_enable = true;
 var editor_orig_text = '';
 var editor_last_draft = '';
+var page_format = 'wikitext';
 
 window.ajaxEditor = function(revid)
 {
@@ -146,15 +147,15 @@
 		span_mce.appendChild(a);
 		toggler.appendChild(span_mce);
 		
-		if ( response.page_format == 'xhtml' )
+		if ( response.page_format == 'wikitext' )
 		{
-			// Current selection is TinyMCE - make span_wiki have the link and span_mce be plaintext
-			span_mce.style.display = 'none';
+			// Current selection is a custom editor plugin - make span_wiki have the link and span_mce be plaintext
+			span_wiki.style.display = 'none';
 		}
 		else
 		{
 			// Current selection is wikitext - set span_wiki to plaintext and span_mce to link
-			span_wiki.style.display = 'none';
+			span_mce.style.display = 'none';
 		}
 	}
 	
@@ -493,9 +494,32 @@
 	editor_orig_text = content;
 	
 	// If the editor preference is tinymce, switch the editor to TinyMCE now
-	if ( response.page_format == 'xhtml' && allow_wysiwyg )
+	if ( response.page_format != 'wikitext' && allow_wysiwyg )
 	{
-		$dynano('ajaxEditArea').switchToMCE(false);
+		if ( typeof(editor_formats[response.page_format]) == 'object' )
+		{
+			// instruct the editor plugin to go ahead and build its UI
+			editor_formats[response.page_format].ui_construct();
+			window.page_format = response.page_format;
+		}
+		else
+		{
+			// Page was formatted with a plugin that no longer exists
+			miniPromptMessage({
+				title: $lang.get('editor_msg_convert_missing_plugin_title'),
+				message: $lang.get('editor_msg_convert_missing_plugin_body', { plugin: response.page_format }),
+				buttons: [
+					{
+						text: $lang.get('etc_ok'),
+						onclick: function()
+						{
+							miniPromptDestroy(this);
+							return false;
+						}
+					}
+				]
+			});
+		}
 	}
 	
 	if ( allow_wysiwyg )
@@ -549,7 +573,7 @@
 	else
 		editor_save_lock = true;
 	
-	var ta_content = ( text_override ) ? text_override : $dynano('ajaxEditArea').getContent();
+	var ta_content = ( text_override ) ? text_override : ajaxEditorGetContent();
 	
 	if ( !is_draft && ( ta_content == '' || ta_content == '<p></p>' || ta_content == '<p>&nbsp;</p>' ) )
 	{
@@ -585,7 +609,7 @@
 		minor_edit: is_minor,
 		time: timestamp,
 		draft: ( is_draft == true ),
-		format: ( $dynano('ajaxEditArea').isMCE() ) ? 'xhtml' : 'wikitext',
+		format: window.page_format,
 		used_draft: used_draft
 	};
 	
@@ -696,7 +720,13 @@
 						editor_open = false;
 						editor_save_lock = false;
 						enableUnload();
-						$dynano('ajaxEditArea').destroyMCE(false);
+						if ( window.page_format != 'wikitext' )
+						{
+							if ( typeof(editor_formats[window.page_format].ui_destroy) == 'function' )
+							{
+								editor_formats[window.page_format].ui_destroy();
+							}
+						}
 						changeOpac(0, 'ajaxEditContainer');
 						ajaxGet(stdAjaxPrefix + '&_mode=getpage&noheaders', function(ajax)
 							{
@@ -759,7 +789,7 @@
 window.ajaxEditorGenPreview = function()
 {
 	ajaxSetEditorLoading();
-	var ta_content = $dynano('ajaxEditArea').getContent();
+	var ta_content = ajaxEditorGetContent();
 	ta_content = ajaxEscape(ta_content);
 	if ( $dynano('enano_editor_preview').object.innerHTML != '' )
 	{
@@ -853,7 +883,7 @@
 window.ajaxEditorShowDiffs = function()
 {
 	ajaxSetEditorLoading();
-	var ta_content = $dynano('ajaxEditArea').getContent();
+	var ta_content = ajaxEditorGetContent();
 	ta_content = ajaxEscape(ta_content);
 	if ( $dynano('enano_editor_preview').object.innerHTML != '' )
 	{
@@ -909,32 +939,24 @@
 		});
 }
 
-window.ajaxSetEditorMCE = function(confirmed)
+window.ajaxSetEditorMCE = function()
 {
 	if ( editor_loading )
 		return false;
 	
-	if ( !confirmed )
+	var len = 0;
+	for ( var i in editor_formats )
+	{
+		len++;
+	}
+	
+	if ( len == 0 )
 	{
 		miniPromptMessage({
-				title: $lang.get('editor_msg_convert_confirm_title'),
-				message: $lang.get('editor_msg_convert_confirm_body'),
+				title: $lang.get('editor_msg_convert_no_plugins_title'),
+				message: $lang.get('editor_msg_convert_no_plugins_body'),
 				buttons: [
 					{
-						color: 'blue',
-						text: $lang.get('editor_btn_graphical'),
-						style: {
-							fontWeight: 'bold'
-						},
-						sprite: [ editor_img_path + '/sprite.png', 16, 16, 0, 112 ],
-						onclick: function()
-						{
-							ajaxSetEditorMCE(true);
-							miniPromptDestroy(this);
-							return false;
-						}
-					},
-					{
 						text: $lang.get('etc_cancel'),
 						onclick: function()
 						{
@@ -947,14 +969,46 @@
 		return false;
 	}
 	
-	// Clear out existing buttons
-	var span_wiki = $dynano('enano_edit_btn_pt').object;
-	var span_mce  = $dynano('enano_edit_btn_mce').object;
-	span_wiki.style.display = 'inline';
-	span_mce.style.display = 'none';
+	var mp = miniPrompt(function(div)
+		{
+			$(div).css('text-align', 'center');
+			$(div).append('<h3>' + $lang.get('editor_msg_convert_confirm_title') + '</h3>');
+			$(div).append('<p>' + $lang.get('editor_msg_convert_confirm_body') + '</p>');
+			var select = '<select class="format">';
+			for ( var i in editor_formats )
+			{
+				var obj = editor_formats[i];
+				select += '<option value="' + i + '">' + $lang.get(obj.name) + '</option>';
+			}
+			select += '</select>';
+			
+			$(div).append('<p class="format_drop">' + $lang.get('editor_msg_convert_lbl_plugin') + select + '</p>');
+			$(div).append('<p><a href="#" class="abutton abutton_green go_action" style="font-weight: bold;">' + gen_sprite_html(editor_img_path + '/sprite.png', 16, 16, 0, 112) + $lang.get('editor_btn_graphical_convert') + '</a>'
+					+ '<a href="#" class="abutton cancel_action">' + $lang.get('etc_cancel') + '</a></p>');
+			
+			$('a.go_action', div).click(function()
+				{
+					// go ahead with converting to this format
+					
+					var parent = miniPromptGetParent(this);
+					var whitey = whiteOutMiniPrompt(parent);
+					var plugin = $('select.format', parent).val();
+					ajaxEditorSetFormat(plugin, function()
+						{
+							if ( typeof(whitey) == 'object' )
+								whiteOutReportSuccess(whitey);
+						});
+					return false;
+				});
+			
+			$('a.cancel_action', div).click(function()
+				{
+					miniPromptDestroy(this);
+					return false;
+				});
+		});
 	
-	// Swap editor
-	$dynano('ajaxEditArea').switchToMCE(true);
+	return false;
 }
 
 window.ajaxSetEditorPlain = function(confirmed)
@@ -1002,7 +1056,20 @@
 	span_mce.style.display = 'inline';
 	
 	// Swap editor
-	$dynano('ajaxEditArea').destroyMCE(true);
+	if ( typeof(editor_formats[window.page_format].ui_destroy) == 'function' )
+	{
+		if ( typeof(editor_formats[window.page_format].convert_from) == 'function' )
+		{
+			var text = ajaxEditorGetContent();
+			var newtext = editor_formats[window.page_format].convert_from(text);
+			if ( typeof(newtext) != 'string' )
+				newtext = text;
+		}
+		editor_formats[window.page_format].ui_destroy();
+		$('#ajaxEditArea').val(newtext);
+	}
+	
+	window.page_format = 'wikitext';
 }
 
 var editor_loading = false;
@@ -1084,7 +1151,7 @@
 	var now = unix_time();
 	aed.as_last_save = now;
 	
-	var ta_content = $dynano('ajaxEditArea').getContent();
+	var ta_content = ajaxEditorGetContent();
 	
 	if ( ta_content == '' || ta_content == '<p></p>' || ta_content == '<p>&nbsp;</p>' || ta_content == editor_orig_text || ta_content == editor_last_draft )
 	{
@@ -1125,7 +1192,22 @@
 				
 				editor_convert_if_needed(response.page_format);
 				
-				$dynano('ajaxEditArea').setContent(response.src);
+				if ( response.page_format != 'wikitext' && typeof(editor_formats[response.page_format]) == 'object' )
+				{
+					if ( typeof(editor_formats[response.page_format].set_text) == 'function' )
+					{
+						editor_formats[response.page_format].set_text(response.src);
+					}
+					else
+					{
+						$('#ajaxEditArea').val(response.src);
+					}
+				}
+				else
+				{
+					$('#ajaxEditArea').val(response.src);
+				}
+				
 				$dynano('ajaxEditArea').object.used_draft = true;
 				editor_orig_text = editor_last_draft = response.src;
 				
@@ -1144,12 +1226,12 @@
 window.editor_convert_if_needed = function(targetformat, noticetitle, noticebody)
 {
 	// Do we need to change the format?
-	var need_to_mce = ( targetformat == 'xhtml' && !$dynano('ajaxEditArea').isMCE() );
-	var need_to_wkt = ( targetformat == 'wikitext' && $dynano('ajaxEditArea').isMCE() );
+	var need_to_mce = ( targetformat != 'wikitext' && page_format == 'wikitext' );
+	var need_to_wkt = ( targetformat == 'wikitext' && page_format != 'wikitext' );
 	if ( need_to_mce )
 	{
-		$dynano('ajaxEditArea').setContent('');
-		$dynano('ajaxEditArea').switchToMCE(false);
+		editor_formats[targetformat].ui_construct();
+		window.page_format = targetformat;
 		
 		// Clear out existing buttons
 		var span_wiki = $dynano('enano_edit_btn_pt').object;
@@ -1159,8 +1241,8 @@
 	}
 	else if ( need_to_wkt )
 	{
-		$dynano('ajaxEditArea').setContent('');
-		$dynano('ajaxEditArea').destroyMCE(false);
+		editor_formats[window.page_format].ui_construct();
+		window.page_format = 'wikitext';
 		
 		// Clear out existing buttons
 		var span_wiki = $dynano('enano_edit_btn_pt').object;
@@ -1192,3 +1274,51 @@
 			});
 	}
 }
+
+window.ajaxEditorSetFormat = function(plugin, success_func)
+	{
+		// perform conversion
+		if ( typeof(editor_formats[plugin].convert_to) == 'function' )
+		{
+			var result = editor_formats[plugin].convert_to($('#ajaxEditArea').val());
+		}
+		else
+		{
+			var result = $('#ajaxEditArea').val();
+		}
+		if ( typeof(result) != 'string' )
+		{
+			result = $('#ajaxEditArea').val();
+		}
+		$('#ajaxEditArea').val(result);
+		if ( typeof(editor_formats[plugin].ui_construct) == 'function' )
+		{
+			editor_formats[plugin].ui_construct();
+		}
+		success_func();
+		window.page_format = plugin;
+		
+		// change the buttons over
+		$('#enano_edit_btn_pt').css('display', 'inline');
+		$('#enano_edit_btn_mce').css('display', 'none');
+	};
+	
+window.ajaxEditorGetContent = function()
+	{
+		if ( window.page_format == 'wikitext' )
+		{
+			return $('#ajaxEditArea').val();
+		}
+		else
+		{
+			if ( typeof(editor_formats[window.page_format].get_text) == 'function' )
+			{
+				return editor_formats[window.page_format].get_text();
+			}
+			else
+			{
+				return $('#ajaxEditArea').val();
+			}
+		}
+	};
+
--- a/includes/clientside/static/enano-lib-basic.js	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/clientside/static/enano-lib-basic.js	Thu Jun 02 05:28:28 2011 -0400
@@ -43,7 +43,6 @@
 
 var detect = navigator.userAgent.toLowerCase();
 var IE;
-var is_Safari;
 
 // Detect whether the user is running the Evil One or not...
 
@@ -61,9 +60,12 @@
 var is_Webkit = checkIt('applewebkit');
 var is_Gecko = checkIt('gecko');
 var is_firefox2 = checkIt('firefox/2.');
+var is_Safari = checkIt('safari') ? true : false;
 
 var KILL_SWITCH = false;
 
+var editor_formats = {};
+
 if ( IE )
 {
 	var version = window.navigator.appVersion;
@@ -92,8 +94,6 @@
 	var DISABLE_MCE = false;
 }
 
-is_Safari = checkIt('safari') ? true : false;
-
 var cmt_open;
 var editor_open = false;
 var list;
--- a/includes/common.php	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/common.php	Thu Jun 02 05:28:28 2011 -0400
@@ -46,7 +46,7 @@
 // This is incremented each time a change to the database structure is made.
 // If it doesn't match the version in the DB, the user will be asked to upgrade.
 // This must match install/includes/common.php!
-$db_version = 1125;
+$db_version = 1126;
 
 /**
  * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it
--- a/includes/namespaces/default.php	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/namespaces/default.php	Thu Jun 02 05:28:28 2011 -0400
@@ -426,16 +426,21 @@
 		
 		if ( $incl_inner_headers )
 		{
-			if ( $page_format === 'wikitext' )
+			if ( $page_format === 'wikitext' || !function_exists("render_text_{$page_format}") )
 			{
 				$text = '?>' . RenderMan::render($text);
 			}
 			else
 			{
+				$result = call_user_func("render_text_{$page_format}", $text);
+				if ( is_string($result) )
+				{
+					$text = $result;
+					unset($result);
+				}
 				// Page format is XHTML. This means we want to disable functionality that MCE takes care of, while still retaining
 				// the ability to wikilink, the ability to use images, etc. Basically, RENDER_INLINEONLY disables all behavior in
 				// the rendering engine/Text_Wiki that conflicts with MCE.
-				$text = '?>' . RenderMan::render($text, RENDER_INLINE);
 			}
 		}
 		else
--- a/includes/pageprocess.php	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/pageprocess.php	Thu Jun 02 05:28:28 2011 -0400
@@ -366,12 +366,12 @@
  	* @param string The new text for the page
  	* @param string A summary of edits made to the page.
  	* @param bool If true, the edit is marked as a minor revision
- 	* @param string Page format - wikitext or xhtml. REQUIRED, and new in 1.1.6.
+ 	* @param string Page format. New in 1.1.6; defaults to "wikitext"
  	* @param array Optional - the entire incoming request. Plugins can add their own data to it.
  	* @return bool True on success, false on failure. When returning false, it will push errors to the PageProcessor error stack; read with $page->pop_error()
  	*/
 	
-	function update_page($text, $edit_summary = false, $minor_edit = false, $page_format, $raw_request = array())
+	function update_page($text, $edit_summary = false, $minor_edit = false, $page_format = 'wikitext', $raw_request = array())
 	{
 		global $db, $session, $paths, $template, $plugins; // Common objects
 		global $lang;
@@ -444,9 +444,10 @@
 		}
 		
 		// Page format check
-		if ( !in_array($page_format, array('xhtml', 'wikitext')) )
+		$page_format = $db->escape($page_format);
+		if ( !preg_match('/^[a-z0-9_]+$/', $page_format) )
 		{
-			$this->raise_error("format \"$page_format\" not one of [xhtml, wikitext]");
+			$this->raise_error('Page format must match /^[a-z0-9_]+$/');
 			return false;
 		}
 		
--- a/includes/render.php	Thu Jun 02 05:24:38 2011 -0400
+++ b/includes/render.php	Thu Jun 02 05:28:28 2011 -0400
@@ -241,7 +241,7 @@
 		{
 			// inline only
 			$carpenter->disable_all_rules();
-			foreach ( array('bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule )
+			foreach ( array('heading', 'bold', 'italic', 'underline', 'externalwithtext', 'externalnotext', 'image', 'internallink') as $rule )
 			{
 				$carpenter->enable_rule($rule);
 			}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/mysql/1126.sql	Thu Jun 02 05:28:28 2011 -0400
@@ -0,0 +1,2 @@
+UPDATE {{TABLE_PREFIX}}pages SET page_format = 'tinymce' WHERE page_format = 'xhtml';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/postgresql/1126.sql	Thu Jun 02 05:28:28 2011 -0400
@@ -0,0 +1,2 @@
+-- Postgres never did have a constraint on this column.
+UPDATE {{TABLE_PREFIX}}pages SET page_format = 'tinymce' WHERE page_format = 'xhtml';
--- a/language/english/core.json	Thu Jun 02 05:24:38 2011 -0400
+++ b/language/english/core.json	Thu Jun 02 05:28:28 2011 -0400
@@ -387,10 +387,16 @@
 			msg_have_draft_body: '%author% saved a draft version of this page on %time%. You can <a href="#use_draft" onclick="ajaxEditorUseDraft(); return false;">use the draft copy</a>, or edit the current published version (below). If you edit the published version, the draft copy will remain available, but will not reflect your changes. It is recommended that you edit the draft version instead of editing the published version. You can also <a href="#delete_draft" onclick="ajaxEditorDeleteDraft(); return false;">discard the draft revision</a>.',
 			msg_convert_confirm_title: 'Convert this page?',
 			msg_convert_confirm_body: 'This will change the format of the page. This may cause some loss of formatting information.',
+			msg_convert_no_plugins_title: 'Unable to convert page',
+			msg_convert_no_plugins_body: 'There are no editor UI plugins installed on this site.',
+			msg_convert_missing_plugin_title: 'Missing editor plugin',
+			msg_convert_missing_plugin_body: 'This page or revision was formatted using the plugin "%plugin%", which is no longer installed on the site. The plain text editor will be used. Some formatting information may not be correct.',
 			msg_convert_draft_load_title: 'Format changed',
 			msg_convert_draft_load_body: 'The revision that was just loaded is in a different format than the current setting. The editor has been switched to match the format.',
-			btn_graphical: 'Convert to HTML',
-			btn_wikitext: 'Convert to wikitext',
+			msg_convert_lbl_plugin: 'Editor plugin: ',
+			btn_graphical: 'Use another format',
+			btn_graphical_convert: 'Convert page',
+			btn_wikitext: 'Convert to plain text',
 			lbl_edit_summary: 'Brief summary of your changes:',
 			lbl_edit_summary_explain: 'Please summarize and briefly explain what you changed on the page.',
 			lbl_minor_edit: 'Mark revision as trivial:',
@@ -576,7 +582,7 @@
 			edit_comments: 'Edit own comments',
 			edit_page: 'Edit page',
 			view_source: 'View source',
-			edit_wysiwyg: 'Use graphical editor (<a href="http://docs.enanocms.org/Help:4.1#toc4">WEAK</a>)',
+			edit_wysiwyg: 'Use alternate editor engines (<a href="http://docs.enanocms.org/Help:4.1#head:Default_values">WEAK</a>)',
 			mod_comments: 'Moderate comments',
 			history_view: 'View history/diffs',
 			history_rollback: 'Rollback history',