From 0a7d8833986ff440d267bdef7dafb22c55960287 Mon Sep 17 00:00:00 2001 From: TimotheeHrl Date: Mon, 18 Dec 2023 11:37:19 +0100 Subject: [PATCH 1/5] LUT-25131 : Modernize the markup language used --- pom.xml | 6 + .../wiki/business/ITopicVersionDAO.java | 1 + .../plugins/wiki/business/TopicDAO.java | 57 +- .../plugins/wiki/business/TopicHome.java | 3 +- .../wiki/business/TopicVersionDAO.java | 340 +- .../plugins/wiki/business/WikiContent.java | 41 +- .../wiki/resources/wiki_messages.properties | 16 +- .../resources/wiki_messages_fr.properties | 2 +- .../plugins/wiki/search/WikiIndexer.java | 9 +- .../wiki/service/ContentDeserializer.java | 92 + .../plugins/wiki/service/DiffService.java | 1 - .../plugins/wiki/service/PathService.java | 2 +- .../lutece/plugins/wiki/service/WikiDiff.java | 2 +- .../WikiExtendableResourceService.java | 2 +- .../plugins/wiki/service/WikiService.java | 70 +- .../wiki/service/parser/LuteceHtmlParser.java | 168 + .../wiki/service/parser/LuteceWikiParser.java | 49 +- .../wiki/service/parser/SpecialChar.java | 44 + .../service/parser/WikiCreoleToMarkdown.java | 206 + .../wiki/utils/auth/WikiAnonymousUser.java | 34 + .../lutece/plugins/wiki/web/Constants.java | 16 +- .../lutece/plugins/wiki/web/WikiApp.java | 546 +- .../plugins/wiki/web/WikiDynamicInputs.java | 145 + .../plugins/wiki/plugin/create_db_wiki.sql | 1 + src/sql/plugins/wiki/plugin/init_db_wiki.sql | 16 - .../upgrade/update_db_wiki-3.0.1-3.0.2.sql | 3 +- webapp/WEB-INF/plugins/wiki.xml | 9 +- .../plugins/wiki/custom_input_editor.html | 139 + .../skin/plugins/wiki/diff_topic.html | 13 +- .../skin/plugins/wiki/history_page.html | 90 +- .../skin/plugins/wiki/modify_page.html | 588 +- .../skin/plugins/wiki/preview_page.html | 22 - .../skin/plugins/wiki/syntax_help.html | 192 +- .../skin/plugins/wiki/view_page.html | 79 +- webapp/css/plugins/wiki/darkmode.css | 133 + webapp/css/plugins/wiki/prism/prism.css | 3 + ...ditor-plugin-code-syntax-highlight.min.css | 6 + ...toastui-editor-plugin-color-syntax.min.css | 6 + ...ui-editor-plugin-table-merged-cell.min.css | 6 + .../wiki/toastui/toastui-editor-dark.css | 480 + .../plugins/wiki/toastui/toastui-editor.css | 1599 + .../plugins/wiki/toastui/tui-color-picker.css | 154 + webapp/css/plugins/wiki/toggle_switch.css | 59 + webapp/css/plugins/wiki/wiki.css | 74 +- webapp/js/plugins/wiki/latex_js/latex.js | 3 + webapp/js/plugins/wiki/prism/prism.js | 20 + .../tui_color_picker/tui-color-picker.min.js | 9 + .../wiki/tui_editor/cdn/toastui-editor-all.js | 40800 ++++++++++++++++ .../tui_editor/cdn/toastui-editor-all.min.js | 24 + ...editor-plugin-code-syntax-highlight-all.js | 19559 ++++++++ ...or-plugin-code-syntax-highlight-all.min.js | 15 + .../cdn/toastui-editor-plugin-color-syntax.js | 320 + .../toastui-editor-plugin-color-syntax.min.js | 7 + ...tui-editor-plugin-table-merged-cell.min.js | 7 + .../wiki/wiki_pages/defaultEditorContent.js | 186 + .../plugins/wiki/wiki_pages/history_page.js | 5 + .../js/plugins/wiki/wiki_pages/modify_page.js | 586 + .../js/plugins/wiki/wiki_pages/view_page.js | 95 + .../site/plugins/wiki/WikiDynamicInputs.jsp | 10 + 59 files changed, 65999 insertions(+), 1171 deletions(-) create mode 100644 src/java/fr/paris/lutece/plugins/wiki/service/ContentDeserializer.java create mode 100644 src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceHtmlParser.java create mode 100644 src/java/fr/paris/lutece/plugins/wiki/service/parser/SpecialChar.java create mode 100644 src/java/fr/paris/lutece/plugins/wiki/service/parser/WikiCreoleToMarkdown.java create mode 100644 src/java/fr/paris/lutece/plugins/wiki/web/WikiDynamicInputs.java create mode 100644 webapp/WEB-INF/templates/skin/plugins/wiki/custom_input_editor.html delete mode 100644 webapp/WEB-INF/templates/skin/plugins/wiki/preview_page.html create mode 100644 webapp/css/plugins/wiki/darkmode.css create mode 100644 webapp/css/plugins/wiki/prism/prism.css create mode 100644 webapp/css/plugins/wiki/toastui/plugins/min/toastui-editor-plugin-code-syntax-highlight.min.css create mode 100644 webapp/css/plugins/wiki/toastui/plugins/min/toastui-editor-plugin-color-syntax.min.css create mode 100644 webapp/css/plugins/wiki/toastui/plugins/min/toastui-editor-plugin-table-merged-cell.min.css create mode 100644 webapp/css/plugins/wiki/toastui/toastui-editor-dark.css create mode 100644 webapp/css/plugins/wiki/toastui/toastui-editor.css create mode 100644 webapp/css/plugins/wiki/toastui/tui-color-picker.css create mode 100644 webapp/css/plugins/wiki/toggle_switch.css create mode 100644 webapp/js/plugins/wiki/latex_js/latex.js create mode 100644 webapp/js/plugins/wiki/prism/prism.js create mode 100644 webapp/js/plugins/wiki/tui_color_picker/tui-color-picker.min.js create mode 100644 webapp/js/plugins/wiki/tui_editor/cdn/toastui-editor-all.js create mode 100644 webapp/js/plugins/wiki/tui_editor/cdn/toastui-editor-all.min.js create mode 100644 webapp/js/plugins/wiki/tui_editor/plugins/editor-plugin-code-syntax-highlight/cdn/toastui-editor-plugin-code-syntax-highlight-all.js create mode 100644 webapp/js/plugins/wiki/tui_editor/plugins/editor-plugin-code-syntax-highlight/cdn/toastui-editor-plugin-code-syntax-highlight-all.min.js create mode 100644 webapp/js/plugins/wiki/tui_editor/plugins/editor-plugin-color-syntax/cdn/toastui-editor-plugin-color-syntax.js create mode 100644 webapp/js/plugins/wiki/tui_editor/plugins/editor-plugin-color-syntax/cdn/toastui-editor-plugin-color-syntax.min.js create mode 100644 webapp/js/plugins/wiki/tui_editor/plugins/editor-plugin-table-merged-cell/cdn/toastui-editor-plugin-table-merged-cell.min.js create mode 100644 webapp/js/plugins/wiki/wiki_pages/defaultEditorContent.js create mode 100644 webapp/js/plugins/wiki/wiki_pages/history_page.js create mode 100644 webapp/js/plugins/wiki/wiki_pages/modify_page.js create mode 100644 webapp/js/plugins/wiki/wiki_pages/view_page.js create mode 100644 webapp/jsp/site/plugins/wiki/WikiDynamicInputs.jsp diff --git a/pom.xml b/pom.xml index 3d4c327b..823071fa 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,12 @@ 2.4 jdk15 + + + com.vladsch.flexmark + flexmark-all + 0.62.2 + diff --git a/src/java/fr/paris/lutece/plugins/wiki/business/ITopicVersionDAO.java b/src/java/fr/paris/lutece/plugins/wiki/business/ITopicVersionDAO.java index b18aaff5..e52ac4e4 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/business/ITopicVersionDAO.java +++ b/src/java/fr/paris/lutece/plugins/wiki/business/ITopicVersionDAO.java @@ -75,6 +75,7 @@ public interface ITopicVersionDAO */ TopicVersion load( int nKey, Plugin plugin ); + void deleteByTopicVersion(int nTopicId, Plugin plugin); /** * Load the data of all the topicVersion objects and returns them as a collection * diff --git a/src/java/fr/paris/lutece/plugins/wiki/business/TopicDAO.java b/src/java/fr/paris/lutece/plugins/wiki/business/TopicDAO.java index 1fdf8dcf..2c80f963 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/business/TopicDAO.java +++ b/src/java/fr/paris/lutece/plugins/wiki/business/TopicDAO.java @@ -47,12 +47,11 @@ public final class TopicDAO implements ITopicDAO // Constants private static final String SQL_QUERY_NEW_PK = "SELECT max( id_topic ) FROM wiki_topic"; private static final String SQL_QUERY_SELECT = "SELECT id_topic, namespace, page_name, page_view_role, page_edit_role, parent_page_name FROM wiki_topic WHERE id_topic = ?"; - private static final String SQL_QUERY_INSERT = "INSERT INTO wiki_topic ( id_topic, namespace, page_name, page_view_role, page_edit_role, parent_page_name ) VALUES ( ?, ?, ?, ?, ?, ? ) "; + private static final String SQL_QUERY_INSERT = "INSERT INTO wiki_topic ( id_topic, namespace, page_name, page_view_role, page_edit_role, parent_page_name ) VALUES (?, ?, ?, ?, ?, ? ) "; private static final String SQL_QUERY_DELETE = "DELETE FROM wiki_topic WHERE id_topic = ? "; private static final String SQL_QUERY_UPDATE = "UPDATE wiki_topic SET id_topic = ?, namespace = ?, page_name = ?, page_view_role = ?, page_edit_role = ?, parent_page_name = ? WHERE id_topic = ?"; private static final String SQL_QUERY_SELECTALL = "SELECT id_topic, namespace, page_name, page_view_role, page_edit_role, parent_page_name FROM wiki_topic"; private static final String SQL_QUERY_SELECT_BY_NAME = "SELECT id_topic, namespace, page_name, page_view_role, page_edit_role, parent_page_name FROM wiki_topic WHERE page_name = ?"; - /** * Generates a new primary key * @@ -64,7 +63,7 @@ public int newPrimaryKey( Plugin plugin ) { int nKey; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_NEW_PK, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_NEW_PK, plugin ) ) { daoUtil.executeQuery( ); @@ -81,7 +80,7 @@ public int newPrimaryKey( Plugin plugin ) @Override public void insert( Topic topic, Plugin plugin ) { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT, plugin ) ) { topic.setIdTopic( newPrimaryKey( plugin ) ); @@ -104,21 +103,14 @@ public Topic load( int nId, Plugin plugin ) { Topic topic = null; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT, plugin ) ) { daoUtil.setInt( 1, nId ); daoUtil.executeQuery( ); if ( daoUtil.next( ) ) { - topic = new Topic( ); - - topic.setIdTopic( daoUtil.getInt( 1 ) ); - topic.setNamespace( daoUtil.getInt( 2 ) ); - topic.setPageName( daoUtil.getString( 3 ) ); - topic.setViewRole( daoUtil.getString( 4 ) ); - topic.setEditRole( daoUtil.getString( 5 ) ); - topic.setParentPageName( daoUtil.getString( 6 ) ); + topic = setTopicWithDaoUtil(daoUtil); } } @@ -131,7 +123,7 @@ public Topic load( int nId, Plugin plugin ) @Override public void delete( int nTopicId, Plugin plugin ) { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE, plugin ) ) { daoUtil.setInt( 1, nTopicId ); daoUtil.executeUpdate( ); @@ -144,7 +136,7 @@ public void delete( int nTopicId, Plugin plugin ) @Override public void store( Topic topic, Plugin plugin ) { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_UPDATE, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_UPDATE, plugin ) ) { daoUtil.setInt( 1, topic.getIdTopic( ) ); daoUtil.setInt( 2, topic.getNamespace( ) ); @@ -165,20 +157,13 @@ public void store( Topic topic, Plugin plugin ) public Collection selectTopicsList( Plugin plugin ) { Collection topicList = new ArrayList<>( ); - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECTALL, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECTALL, plugin ) ) { daoUtil.executeQuery( ); while ( daoUtil.next( ) ) { - Topic topic = new Topic( ); - - topic.setIdTopic( daoUtil.getInt( 1 ) ); - topic.setNamespace( daoUtil.getInt( 2 ) ); - topic.setPageName( daoUtil.getString( 3 ) ); - topic.setViewRole( daoUtil.getString( 4 ) ); - topic.setEditRole( daoUtil.getString( 5 ) ); - topic.setParentPageName( daoUtil.getString( 6 ) ); + Topic topic = setTopicWithDaoUtil(daoUtil); topicList.add( topic ); } @@ -195,24 +180,30 @@ public Topic load( String strTopicName, Plugin plugin ) { Topic topic = null; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT_BY_NAME, plugin ) ) + try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT_BY_NAME, plugin ) ) { daoUtil.setString( 1, strTopicName ); daoUtil.executeQuery( ); if ( daoUtil.next( ) ) { - topic = new Topic( ); - - topic.setIdTopic( daoUtil.getInt( 1 ) ); - topic.setNamespace( daoUtil.getInt( 2 ) ); - topic.setPageName( daoUtil.getString( 3 ) ); - topic.setViewRole( daoUtil.getString( 4 ) ); - topic.setEditRole( daoUtil.getString( 5 ) ); - topic.setParentPageName( daoUtil.getString( 6 ) ); + topic = setTopicWithDaoUtil(daoUtil); } } return topic; } + /** + * set the content of a topic version with doaUtil + */ + public Topic setTopicWithDaoUtil(DAOUtil daoUtil) { + Topic topic = new Topic( ); + topic.setIdTopic( daoUtil.getInt( 1 ) ); + topic.setNamespace( daoUtil.getInt( 2 ) ); + topic.setPageName( daoUtil.getString( 3 ) ); + topic.setViewRole( daoUtil.getString( 4 ) ); + topic.setEditRole( daoUtil.getString( 5 ) ); + topic.setParentPageName( daoUtil.getString( 6 ) ); + return topic; + } } diff --git a/src/java/fr/paris/lutece/plugins/wiki/business/TopicHome.java b/src/java/fr/paris/lutece/plugins/wiki/business/TopicHome.java index f0375391..d290f52e 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/business/TopicHome.java +++ b/src/java/fr/paris/lutece/plugins/wiki/business/TopicHome.java @@ -119,7 +119,7 @@ public static Topic findByPrimaryKey( int nKey ) * The topic name * @return The topic */ - public static Topic findByPrimaryKey( String strTopicName ) + public static Topic findByPageName( String strTopicName ) { return _dao.load( strTopicName, _plugin ); } @@ -133,4 +133,5 @@ public static Collection getTopicsList( ) { return _dao.selectTopicsList( _plugin ); } + } diff --git a/src/java/fr/paris/lutece/plugins/wiki/business/TopicVersionDAO.java b/src/java/fr/paris/lutece/plugins/wiki/business/TopicVersionDAO.java index e396be5f..792e15b6 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/business/TopicVersionDAO.java +++ b/src/java/fr/paris/lutece/plugins/wiki/business/TopicVersionDAO.java @@ -42,41 +42,37 @@ /** * This class provides Data Access methods for TopicVersion objects */ -public final class TopicVersionDAO implements ITopicVersionDAO -{ +public final class TopicVersionDAO implements ITopicVersionDAO { // Constants private static final String SQL_QUERY_NEW_PK = "SELECT max( id_topic_version ) FROM wiki_topic_version"; - private static final String SQL_QUERY_SELECT = "SELECT id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous,wiki_content FROM wiki_topic_version WHERE id_topic_version = ?"; + private static final String SQL_QUERY_SELECT = "SELECT id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous FROM wiki_topic_version WHERE id_topic_version = ?"; private static final String SQL_QUERY_INSERT = "INSERT INTO wiki_topic_version ( id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous ) VALUES ( ?, ?, ?, ?, ?, ? ) "; private static final String SQL_QUERY_DELETE = "DELETE FROM wiki_topic_version WHERE id_topic_version = ? "; private static final String SQL_QUERY_SELECTALL = "SELECT id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous FROM wiki_topic_version"; - private static final String SQL_QUERY_INSERT_MODIFICATION = "INSERT INTO wiki_topic_version ( id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous ) VALUES ( ?, ?, ?, ?, ?, ?)"; + private static final String SQL_QUERY_INSERT_MODIFICATION = "INSERT INTO wiki_topic_version ( id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous ) VALUES ( ?, ?, ?, ?, ?, ?) "; private static final String SQL_QUERY_SELECT_LAST_BY_TOPIC_ID = "SELECT id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous FROM wiki_topic_version WHERE id_topic = ? ORDER BY date_edition DESC LIMIT 1"; private static final String SQL_QUERY_SELECT_BY_TOPIC_ID = "SELECT id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous FROM wiki_topic_version WHERE id_topic = ? ORDER BY date_edition DESC "; private static final String SQL_QUERY_DELETE_BY_TOPIC_ID = "DELETE FROM wiki_topic_version WHERE id_topic = ? "; - - private static final String SQL_QUERY_SELECT_CONTENT = "SELECT locale, page_title, wiki_content FROM wiki_topic_version_content WHERE id_topic_version = ?"; - private static final String SQL_QUERY_INSERT_CONTENT = "INSERT INTO wiki_topic_version_content ( id_topic_version, locale, page_title, wiki_content ) VALUES ( ?, ?, ?, ? ) "; + private static final String SQL_QUERY_SELECT_CONTENT = "SELECT locale, page_title, wiki_content, html_wiki_content FROM wiki_topic_version_content WHERE id_topic_version = ?"; + private static final String SQL_QUERY_INSERT_CONTENT = "INSERT INTO wiki_topic_version_content ( id_topic_version, locale, page_title, wiki_content, html_wiki_content ) VALUES ( ?, ?, ?, ?, ?) "; private static final String SQL_QUERY_DELETE_CONTENT = "DELETE FROM wiki_topic_version_content WHERE id_topic_version = ? "; private static final String SQL_QUERY_DELETE_CONTENT_BY_TOPIC_ID = "DELETE a.* FROM wiki_topic_version_content a, wiki_topic_version b WHERE a.id_topic_version = b.id_topic_version AND b.id_topic = ? "; + private static final String SQL_QUERY_DELETE_CONTENT_BY_TOPIC_VERSION_ID = "DELETE FROM wiki_topic_version_content WHERE id_topic_version = ? "; + private static final String SQL_QUERY_DELETE_BY_TOPIC_VERSION_ID = "DELETE FROM wiki_topic_version WHERE id_topic_version = ? "; - /** - * Generates a new primary key + /* Generates a new primary key * - * @param plugin - * The Plugin + * @param plugin The Plugin * @return The new primary key */ - public int newPrimaryKey( Plugin plugin ) - { + public int newPrimaryKey(Plugin plugin) { int nKey; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_NEW_PK, plugin ) ) - { - daoUtil.executeQuery( ); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_NEW_PK, plugin)) { + daoUtil.executeQuery(); - daoUtil.next( ); - nKey = daoUtil.getInt( 1 ) + 1; + daoUtil.next(); + nKey = daoUtil.getInt(1) + 1; } return nKey; @@ -86,33 +82,30 @@ public int newPrimaryKey( Plugin plugin ) * {@inheritDoc } */ @Override - public void insert( TopicVersion topicVersion, Plugin plugin ) - { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT, plugin ) ) - { + public void insert(TopicVersion topicVersion, Plugin plugin) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_INSERT, plugin)) { - topicVersion.setIdTopicVersion( newPrimaryKey( plugin ) ); + topicVersion.setIdTopicVersion(newPrimaryKey(plugin)); - daoUtil.setInt( 1, topicVersion.getIdTopicVersion( ) ); - daoUtil.setString( 2, topicVersion.getEditComment( ) ); - daoUtil.setInt( 3, topicVersion.getIdTopic( ) ); - daoUtil.setString( 4, topicVersion.getLuteceUserId( ) ); - daoUtil.setTimestamp( 5, topicVersion.getDateEdition( ) ); - daoUtil.setInt( 6, topicVersion.getIdTopicVersionPrevious( ) ); + daoUtil.setInt(1, topicVersion.getIdTopicVersion()); + daoUtil.setString(2, topicVersion.getEditComment()); + daoUtil.setInt(3, topicVersion.getIdTopic()); + daoUtil.setString(4, topicVersion.getLuteceUserId()); + daoUtil.setTimestamp(5, topicVersion.getDateEdition()); + daoUtil.setInt(6, topicVersion.getIdTopicVersionPrevious()); - daoUtil.executeUpdate( ); + daoUtil.executeUpdate(); } - for ( String strLocale : topicVersion.getWikiContents( ).keySet( ) ) - { - WikiContent content = topicVersion.getWikiContent( strLocale ); - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT_CONTENT, plugin ) ) - { - daoUtil.setInt( 1, topicVersion.getIdTopicVersion( ) ); - daoUtil.setString( 2, strLocale ); - daoUtil.setString( 3, content.getPageTitle( ) ); - daoUtil.setString( 4, content.getWikiContent( ) ); - daoUtil.executeUpdate( ); + for (String strLocale : topicVersion.getWikiContents().keySet()) { + WikiContent content = topicVersion.getWikiContent(strLocale); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_INSERT_CONTENT, plugin)) { + daoUtil.setInt(1, topicVersion.getIdTopicVersion()); + daoUtil.setString(2, strLocale); + daoUtil.setString(3, content.getPageTitle()); + daoUtil.setString(4, content.getWikiContent()); + daoUtil.setString(5, content.getHtmlWikiContent()); + daoUtil.executeUpdate(); } } } @@ -121,29 +114,22 @@ public void insert( TopicVersion topicVersion, Plugin plugin ) * {@inheritDoc } */ @Override - public TopicVersion load( int nId, Plugin plugin ) - { + public TopicVersion load(int nId, Plugin plugin) { TopicVersion topicVersion = null; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT, plugin ) ) - { - daoUtil.setInt( 1, nId ); - daoUtil.executeQuery( ); - - if ( daoUtil.next( ) ) - { - topicVersion = new TopicVersion( ); - - topicVersion.setIdTopicVersion( daoUtil.getInt( 1 ) ); - topicVersion.setEditComment( daoUtil.getString( 2 ) ); - topicVersion.setIdTopic( daoUtil.getInt( 3 ) ); - topicVersion.setLuteceUserId( daoUtil.getString( 4 ) ); - topicVersion.setDateEdition( daoUtil.getTimestamp( 5 ) ); - topicVersion.setIdTopicVersionPrevious( daoUtil.getInt( 6 ) ); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_SELECT, plugin)) { + daoUtil.setInt(1, nId); + daoUtil.executeQuery(); + + if (daoUtil.next()) { + topicVersion = setTopicVersionWithDaoUtil(daoUtil); } } - fillContent( topicVersion ); + if (topicVersion != null) { + fillContent(topicVersion); + } + return topicVersion; } @@ -151,23 +137,20 @@ public TopicVersion load( int nId, Plugin plugin ) /** * Fill content * - * @param topicVersion - * the version + * @param topicVersion the version */ - private void fillContent( TopicVersion topicVersion ) - { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT_CONTENT ) ) - { - daoUtil.setInt( 1, topicVersion.getIdTopicVersion( ) ); - daoUtil.executeQuery( ); - while ( daoUtil.next( ) ) - { - WikiContent content = new WikiContent( ); - - String strLanguage = daoUtil.getString( 1 ); - content.setPageTitle( daoUtil.getString( 2 ) ); - content.setWikiContent( daoUtil.getString( 3 ) ); - topicVersion.addLocalizedWikiContent( strLanguage, content ); + private void fillContent(TopicVersion topicVersion) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_SELECT_CONTENT)) { + daoUtil.setInt(1, topicVersion.getIdTopicVersion()); + daoUtil.executeQuery(); + while (daoUtil.next()) { + WikiContent content = new WikiContent(); + + String strLanguage = daoUtil.getString(1); + content.setPageTitle(daoUtil.getString(2)); + content.setWikiContent(daoUtil.getString(3)); + content.setHtmlWikiContent(daoUtil.getString(4)); + topicVersion.addLocalizedWikiContent(strLanguage, content); } } } @@ -176,18 +159,15 @@ private void fillContent( TopicVersion topicVersion ) * {@inheritDoc } */ @Override - public void delete( int nTopicVersionId, Plugin plugin ) - { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE, plugin ) ) - { - daoUtil.setInt( 1, nTopicVersionId ); - daoUtil.executeUpdate( ); + public void delete(int nTopicVersionId, Plugin plugin) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE, plugin)) { + daoUtil.setInt(1, nTopicVersionId); + daoUtil.executeUpdate(); } - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE_CONTENT, plugin ) ) - { - daoUtil.setInt( 1, nTopicVersionId ); - daoUtil.executeUpdate( ); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE_CONTENT, plugin)) { + daoUtil.setInt(1, nTopicVersionId); + daoUtil.executeUpdate(); } } @@ -195,18 +175,30 @@ public void delete( int nTopicVersionId, Plugin plugin ) * {@inheritDoc } */ @Override - public void deleteByTopic( int nTopicId, Plugin plugin ) - { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE_CONTENT_BY_TOPIC_ID, plugin ) ) - { - daoUtil.setInt( 1, nTopicId ); - daoUtil.executeUpdate( ); + public void deleteByTopic(int nTopicId, Plugin plugin) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE_CONTENT_BY_TOPIC_ID, plugin)) { + daoUtil.setInt(1, nTopicId); + daoUtil.executeUpdate(); + } + + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE_BY_TOPIC_ID, plugin)) { + daoUtil.setInt(1, nTopicId); + daoUtil.executeUpdate(); + } + } + /** + * {@inheritDoc } + */ + @Override + public void deleteByTopicVersion(int nTopicVersionId, Plugin plugin) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE_CONTENT_BY_TOPIC_VERSION_ID, plugin)) { + daoUtil.setInt(1, nTopicVersionId); + daoUtil.executeUpdate(); } - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_DELETE_BY_TOPIC_ID, plugin ) ) - { - daoUtil.setInt( 1, nTopicId ); - daoUtil.executeUpdate( ); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_DELETE_BY_TOPIC_VERSION_ID, plugin)) { + daoUtil.setInt(1, nTopicVersionId); + daoUtil.executeUpdate(); } } @@ -214,26 +206,18 @@ public void deleteByTopic( int nTopicId, Plugin plugin ) * {@inheritDoc } */ @Override - public Collection selectTopicVersionsList( Plugin plugin ) - { - Collection topicVersionList = new ArrayList<>( ); - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECTALL, plugin ) ) - { - daoUtil.executeQuery( ); - - while ( daoUtil.next( ) ) - { - TopicVersion topicVersion = new TopicVersion( ); - - topicVersion.setIdTopicVersion( daoUtil.getInt( 1 ) ); - topicVersion.setEditComment( daoUtil.getString( 2 ) ); - topicVersion.setIdTopic( daoUtil.getInt( 3 ) ); - topicVersion.setLuteceUserId( daoUtil.getString( 4 ) ); - topicVersion.setDateEdition( daoUtil.getTimestamp( 5 ) ); - topicVersion.setIdTopicVersionPrevious( daoUtil.getInt( 6 ) ); - fillContent( topicVersion ); - - topicVersionList.add( topicVersion ); + public Collection selectTopicVersionsList(Plugin plugin) { + Collection topicVersionList = new ArrayList<>(); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_SELECTALL, plugin)) { + daoUtil.executeQuery(); + + while (daoUtil.next()) { + TopicVersion topicVersion = new TopicVersion(); + + topicVersion = setTopicVersionWithDaoUtil(daoUtil); + fillContent(topicVersion); + + topicVersionList.add(topicVersion); } } @@ -244,42 +228,37 @@ public Collection selectTopicVersionsList( Plugin plugin ) * {@inheritDoc } */ @Override - public void addTopicVersion( TopicVersion topicVersion, Plugin plugin ) - { - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT_MODIFICATION, plugin ) ) - { - topicVersion.setIdTopicVersion( newPrimaryKey( plugin ) ); - daoUtil.setInt( 1, topicVersion.getIdTopicVersion( ) ); - daoUtil.setString( 2, topicVersion.getEditComment( ) ); - daoUtil.setInt( 3, topicVersion.getIdTopic( ) ); - daoUtil.setString( 4, topicVersion.getUserName( ) ); - daoUtil.setTimestamp( 5, new java.sql.Timestamp( new java.util.Date( ).getTime( ) ) ); - daoUtil.setInt( 6, topicVersion.getIdTopicVersionPrevious( ) ); - - daoUtil.executeUpdate( ); + public void addTopicVersion(TopicVersion topicVersion, Plugin plugin) { + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_INSERT_MODIFICATION, plugin)) { + topicVersion.setIdTopicVersion(newPrimaryKey(plugin)); + daoUtil.setInt(1, topicVersion.getIdTopicVersion()); + daoUtil.setString(2, topicVersion.getEditComment()); + daoUtil.setInt(3, topicVersion.getIdTopic()); + daoUtil.setString(4, topicVersion.getUserName()); + daoUtil.setTimestamp(5, new java.sql.Timestamp(new java.util.Date().getTime())); + daoUtil.setInt(6, topicVersion.getIdTopicVersionPrevious()); + + daoUtil.executeUpdate(); } - storeContent( topicVersion ); + storeContent(topicVersion); } /** * Store the content of a Topic Version * - * @param topicVersion - * The topic Version + * @param topicVersion The topic Version */ - private void storeContent( TopicVersion topicVersion ) - { - for ( String strLanguage : topicVersion.getWikiContents( ).keySet( ) ) - { - WikiContent content = topicVersion.getWikiContents( ).get( strLanguage ); - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_INSERT_CONTENT ) ) - { - daoUtil.setInt( 1, topicVersion.getIdTopicVersion( ) ); - daoUtil.setString( 2, strLanguage ); - daoUtil.setString( 3, content.getPageTitle( ) ); - daoUtil.setString( 4, content.getWikiContent( ) ); - daoUtil.executeUpdate( ); + private void storeContent(TopicVersion topicVersion) { + for (String strLanguage : topicVersion.getWikiContents().keySet()) { + WikiContent content = topicVersion.getWikiContents().get(strLanguage); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_INSERT_CONTENT)) { + daoUtil.setInt(1, topicVersion.getIdTopicVersion()); + daoUtil.setString(2, strLanguage); + daoUtil.setString(3, content.getPageTitle()); + daoUtil.setString(4, content.getWikiContent()); + daoUtil.setString(5, content.getHtmlWikiContent()); + daoUtil.executeUpdate(); } } } @@ -288,31 +267,20 @@ private void storeContent( TopicVersion topicVersion ) * {@inheritDoc } */ @Override - public TopicVersion loadLastVersion( int nIdTopic, Plugin plugin ) - { + public TopicVersion loadLastVersion(int nIdTopic, Plugin plugin) { TopicVersion topicVersion = null; - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT_LAST_BY_TOPIC_ID, plugin ) ) - { - daoUtil.setInt( 1, nIdTopic ); - daoUtil.executeQuery( ); - - if ( daoUtil.next( ) ) - { - topicVersion = new TopicVersion( ); - - topicVersion.setIdTopicVersion( daoUtil.getInt( 1 ) ); - topicVersion.setEditComment( daoUtil.getString( 2 ) ); - topicVersion.setIdTopic( daoUtil.getInt( 3 ) ); - topicVersion.setLuteceUserId( daoUtil.getString( 4 ) ); - topicVersion.setDateEdition( daoUtil.getTimestamp( 5 ) ); - topicVersion.setIdTopicVersionPrevious( daoUtil.getInt( 6 ) ); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_SELECT_LAST_BY_TOPIC_ID, plugin)) { + daoUtil.setInt(1, nIdTopic); + daoUtil.executeQuery(); + + if (daoUtil.next()) { + topicVersion = setTopicVersionWithDaoUtil(daoUtil); } } - if ( topicVersion != null ) - { - fillContent( topicVersion ); + if (topicVersion != null) { + fillContent(topicVersion); } return topicVersion; @@ -322,30 +290,34 @@ public TopicVersion loadLastVersion( int nIdTopic, Plugin plugin ) * {@inheritDoc } */ @Override - public Collection loadAllVersions( int nIdTopic, Plugin plugin ) - { - Collection topicVersionList = new ArrayList<>( ); - try( DAOUtil daoUtil = new DAOUtil( SQL_QUERY_SELECT_BY_TOPIC_ID, plugin ) ) - { - daoUtil.setInt( 1, nIdTopic ); - daoUtil.executeQuery( ); - - while ( daoUtil.next( ) ) - { - TopicVersion topicVersion = new TopicVersion( ); - - topicVersion.setIdTopicVersion( daoUtil.getInt( 1 ) ); - topicVersion.setEditComment( daoUtil.getString( 2 ) ); - topicVersion.setIdTopic( daoUtil.getInt( 3 ) ); - topicVersion.setLuteceUserId( daoUtil.getString( 4 ) ); - topicVersion.setDateEdition( daoUtil.getTimestamp( 5 ) ); - topicVersion.setIdTopicVersionPrevious( daoUtil.getInt( 6 ) ); - fillContent( topicVersion ); - - topicVersionList.add( topicVersion ); + public Collection loadAllVersions(int nIdTopic, Plugin plugin) { + Collection topicVersionList = new ArrayList<>(); + try (DAOUtil daoUtil = new DAOUtil(SQL_QUERY_SELECT_BY_TOPIC_ID, plugin)) { + daoUtil.setInt(1, nIdTopic); + daoUtil.executeQuery(); + + while (daoUtil.next()) { + TopicVersion topicVersion = setTopicVersionWithDaoUtil(daoUtil); + topicVersionList.add(topicVersion); } } return topicVersionList; } -} + /** + * set the content of a topic version with doaUtil + */ + public TopicVersion setTopicVersionWithDaoUtil(DAOUtil daoUtil) { + TopicVersion topicVersion = new TopicVersion(); + topicVersion.setIdTopicVersion(daoUtil.getInt(1)); + topicVersion.setEditComment(daoUtil.getString(2)); + topicVersion.setIdTopic(daoUtil.getInt(3)); + topicVersion.setLuteceUserId(daoUtil.getString(4)); + topicVersion.setDateEdition(daoUtil.getTimestamp(5)); + topicVersion.setIdTopicVersionPrevious(daoUtil.getInt(6)); + + return topicVersion; + } + + +} \ No newline at end of file diff --git a/src/java/fr/paris/lutece/plugins/wiki/business/WikiContent.java b/src/java/fr/paris/lutece/plugins/wiki/business/WikiContent.java index 0dcefc80..10d3e3db 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/business/WikiContent.java +++ b/src/java/fr/paris/lutece/plugins/wiki/business/WikiContent.java @@ -33,6 +33,8 @@ */ package fr.paris.lutece.plugins.wiki.business; +import fr.paris.lutece.plugins.wiki.web.Constants; + /** * WikiContent */ @@ -41,6 +43,7 @@ public class WikiContent // Variables declarations private String _strPageTitle; private String _strWikiContent; + private String _strHtmlWikiContent; /** * Returns the PageTitle @@ -70,7 +73,7 @@ public void setPageTitle( String strPageTitle ) */ public String getWikiContent( ) { - return _strWikiContent; + return _strWikiContent; } /** @@ -83,4 +86,40 @@ public void setWikiContent( String strWikiContent ) { _strWikiContent = strWikiContent; } + + /** + * Returns the HtmlWikiContent + * + * @return The HtmlWikiContent + */ + public String getHtmlWikiContent( ) + { + return _strHtmlWikiContent; + } + + /** + * Sets the HtmlWikiContent + * + * @param strHtmlWikiContent + * The HtmlWikiContent + */ + public void setHtmlWikiContent( String strHtmlWikiContent ) + { + _strHtmlWikiContent = strHtmlWikiContent; + } + + + /** + * Set the WikiContent with labelling MarkdownLanguage + * Labelling MarkdownLanguage is used to avoid to differentiate the content of with previous version of with wiki creole and the new one with markdown + * @param strWikiContent + * The WikiContent + */ + public void setContentLabellingMarkdownLanguage(String strWikiContent ){ + { + _strWikiContent = Constants.MARKDOWN_TAG+strWikiContent; + } + } + + } diff --git a/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages.properties b/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages.properties index afc2dcff..5e844122 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages.properties +++ b/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages.properties @@ -57,7 +57,11 @@ search_wiki.labelItemsPerPage=Number of line per page modify_page.labelComment=Comment modify_page.labelPreview=Preview -modify_page.buttonModify=Save +modify_page.buttonModify=Save in a new version +modify_page.buttonSaveAndOverwrite=Save and overwrite +modify_page.SaveAndPublish=Save and publish +modify_page.CreateNewFromPublished=Create a new version from the published version +modify_page.buttonCancelPublish=Cancel publication modify_page.pageTitle=Page title modify_page.labelParentPageName=Parent page modify_page.titleRole=Access rights @@ -71,6 +75,14 @@ modify_page.titleAddImage=Add an illustration modify_page.labelFile=File modify_page.labelDescription=Description modify_page.buttonUpload=Upload +modify_page.autoSaveSucess=content saved automatically +modify_page.autoSaveFailed=content had not been saved automatically +modify_page.autoSaveDesactivated=Auto save is desactivated +modify_page.autoSaveActivated=Auto save is activated + +somebody_is_editing=is editing this page, please wait or contact this person. +view_page.noPublishedVersion=No published version + ###Messages @@ -92,6 +104,8 @@ message.path.hidden=... message.error.name.notNull=The field Description is mandatory. message.error.file.notNull=The field File is mandatory. +message.cancelBy=Publication canceled by + history_page.explanation=Select versions to compare and click on Modifications to see detailed differences. history_page.tableHeader.mostRecent=Most recent diff --git a/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages_fr.properties b/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages_fr.properties index ec54f282..2b6056e4 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages_fr.properties +++ b/src/java/fr/paris/lutece/plugins/wiki/resources/wiki_messages_fr.properties @@ -1 +1 @@ -plugin.description=Wiki plugin.provider=Mairie de Paris extend.resourceType=Page du Wiki menu.home=Accueil menu.page=Page menu.map=Plan menu.list=Liste menu.preview=Pr\u00e9visualisation menu.search=Recherche menu.edit=Edition menu.create=Cr\u00e9ation menu.history=Historique menu.help=Aide menu.diff=Modifications menu.diff.html=HTML menu.diff.source=Source button.backToPage=Retour \u00e0 la page button.backToEdit=Retour \u00e0 l'\u00e9dition path.map=Plan du wiki title.map=Plan du wiki path.list=Liste des pages title.list=Liste des pages path.search=Recherche dans le Wiki title.search=Recherche dans le Wiki path.labelCreate=-[en cr\u00e9ation] path.labelModify=-[en modification] path.labelHistory=-[historique] path.labelDiff=-[modifications] site_properties_group.name=Propri\u00e9tes du Wiki site_properties_group.description=D\u00e9finit des param\u00e8tres du Wiki site_property.path.rootLabel=Nom racine du Wiki site_property.path.rootLabel.help=Entrer le nom de la racine du Wiki qui s'affichera dans le chemin. site_property.path.rootPageName=Page racine du Wiki site_property.path.rootPageName.help=[Facultatif] permet de d\u00e9finir une page comme \u00e9tant la page racine. site_property.role.admin=Role Administrateur * site_property.role.admin.help=Role de l'administrateur (doit \u00eatre d\u00e9clar\u00e9 dans les r\u00f4les Lutece) site_property.role.view=Role visualiser site_property.role.view.help=[Facultatif] Role par d\u00e9faut pour voir une page, sinon pas de restriction site_property.role.edit=Role modification site_property.role.edit.help=[Facultatif] Role par d\u00e9faut pour modifier une page, sinon pas de restriction site_property.prettify.skin=Th\u00e8me Prettify site_property.prettify.skin.help=Th\u00e8me pour la mise en forme du code : none, sunburst, doxy, desert ou sons-of-obsidian. map_wiki.title=Plan du Wiki list_wiki.title=Liste des pages du Wiki list_wiki.create=Cr\u00e9er une nouvelle page list_wiki.buttonCreate=Nouvelle page modify_page.labelComment=Commentaire concernant les modifications #modify_page.labelPreview=Aper\u00e7u modify_page.buttonModify=Enregistrer modify_page.pageTitle=Titre de la page modify_page.labelParentPageName=Page parent modify_page.titleRole=Droits d'acc\u00e8s modify_page.labelViewRole=R\u00f4le pour voir la page modify_page.labelEditRole=R\u00f4le pour modifier la page modify_page.titleImages=Illustrations modify_page.colImage=Image modify_page.colDescription=Description modify_page.colPasteEditor=Code \u00e0 ins\u00e9rer dans l'\u00e9diteur modify_page.titleAddImage=Ajouter une illustration modify_page.labelFile=Fichier modify_page.labelDescription=Description modify_page.buttonUpload=Uploader ##Messages message.confirmTitle=Attention ! message.confirmRemoveTopic=confirmRemoveTopic message.accessDenied.create.requiresAuthentification= Veuillez vous authentifier afin de cr\u00e9er une page wiki message.accessDenied.modify.requiresAuthentification= Veuillez vous authentifier afin de modifier une page wiki message.accessDenied.pageNotExists=La page wiki n'existe pas message.accessDenied.pageAlreadyExists=La page wiki existe d\u00e9j\u00e0 message.confirmDelete=Etes vous s\u00fbr de vouloir supprimer cette page et tous ses \u00e9l\u00e9ments associ\u00e9s ( illustrations, historique, ...) ? message.accessDenied.userNotInRole=Vous ne disposez pas des autorisations n\u00e9cessaires pour consulter cette page. message.confirmRemoveVersion=Etes vous s\u00fbr de vouloir supprimer cette version de l'historique ? message.version.removed=Version supprim\u00e9e avec succ\u00e8s de l'historique. message.confirmRemoveImage=Etes vous s\u00fbr de vouloir supprimer cette image ? message.image.removed=Image supprim\u00e9e message.authenticationRequired=Le Wiki n\u00e9cessite une authentification via MyLutece !
Veuillez installer ou configurer le syst\u00e8me d'authentification SVP. message.path.hidden=... message.error.name.notNull=Le champ Description est obligatoire. message.error.file.notNull=Le champ Fichier est obligatoire. search_wiki.title=R\u00e9sultats de la recherche search_wiki.search=Termes recherch\u00e9s search_wiki.labelItemsPerPage=Nombre de r\u00e9sultats par page history_page.explanation=S\u00e9lectionner les versions \u00e0 comparer et cliquer sur Modifications pour afficher le d\u00e9tail des diff\u00e9rences. history_page.tableHeader.mostRecent=plus r\u00e9cente history_page.tableHeader.lessRecent=moins r\u00e9cente history_page.tableHeader.date=Date de la modification history_page.tableHeader.author=Auteur history_page.tableHeader.comment=Commentaire \ No newline at end of file +plugin.description=Wiki plugin.provider=Mairie de Paris extend.resourceType=Page du Wiki menu.home=Accueil menu.page=Page menu.map=Plan menu.list=Liste menu.preview=Pr\u00e9visualisation menu.search=Recherche menu.edit=Edition menu.create=Cr\u00e9ation menu.history=Historique menu.help=Aide menu.diff=Modifications menu.diff.html=HTML menu.diff.source=Source button.backToPage=Retour \u00e0 la page button.backToEdit=Retour \u00e0 l'\u00e9dition path.map=Plan du wiki title.map=Plan du wiki path.list=Liste des pages title.list=Liste des pages path.search=Recherche dans le Wiki title.search=Recherche dans le Wiki path.labelCreate=-[en cr\u00e9ation] path.labelModify=-[en modification] path.labelHistory=-[historique] path.labelDiff=-[modifications] site_properties_group.name=Propri\u00e9tes du Wiki site_properties_group.description=D\u00e9finit des param\u00e8tres du Wiki site_property.path.rootLabel=Nom racine du Wiki site_property.path.rootLabel.help=Entrer le nom de la racine du Wiki qui s'affichera dans le chemin. site_property.path.rootPageName=Page racine du Wiki site_property.path.rootPageName.help=[Facultatif] permet de d\u00e9finir une page comme \u00e9tant la page racine. site_property.role.admin=Role Administrateur * site_property.role.admin.help=Role de l'administrateur (doit \u00eatre d\u00e9clar\u00e9 dans les r\u00f4les Lutece) site_property.role.view=Role visualiser site_property.role.view.help=[Facultatif] Role par d\u00e9faut pour voir une page, sinon pas de restriction site_property.role.edit=Role modification site_property.role.edit.help=[Facultatif] Role par d\u00e9faut pour modifier une page, sinon pas de restriction site_property.prettify.skin=Th\u00e8me Prettify site_property.prettify.skin.help=Th\u00e8me pour la mise en forme du code : none, sunburst, doxy, desert ou sons-of-obsidian. map_wiki.title=Plan du Wiki list_wiki.title=Liste des pages du Wiki list_wiki.create=Cr\u00e9er une nouvelle page list_wiki.buttonCreate=Nouvelle page modify_page.labelComment=Commentaire concernant les modifications #modify_page.labelPreview=Aper\u00e7u modify_page.pageTitle=Titre de la page modify_page.labelParentPageName=Page parent modify_page.titleRole=Droits d'acc\u00e8s modify_page.labelViewRole=R\u00f4le pour voir la page modify_page.labelEditRole=R\u00f4le pour modifier la page modify_page.titleImages=Illustrations modify_page.colImage=Image modify_page.colDescription=Description modify_page.colPasteEditor=Code \u00e0 ins\u00e9rer dans l'\u00e9diteur modify_page.titleAddImage=Ajouter une illustration modify_page.labelFile=Fichier modify_page.labelDescription=Description modify_page.buttonUpload=Uploader modify_page.buttonModify=Sauvegarder dans une nouvelle version modify_page.buttonSaveAndOverwrite=Sauvegarder et \u00e9craser modify_page.SaveAndPublish=Sauvegarder et publier modify_page.CreateNewFromPublished=Cr\u00e9er une nouvelle version de la version publi\u00e9e modify_page.buttonCancelPublish=Annuler la publication modify_page.autoSaveSucess=contenu sauvegard\u00e9 automatiquement modify_page.autoSaveFailed=Erreur lors de la sauvegarde automatique modify_page.autoSaveDesactivated=La sauvegarde automatique est d\u00e9sactiv\u00e9e modify_page.autoSaveActivated=La sauvegarde automatique est activ\u00e9e somebody_is_editing=est en train de modifier cette page, merci d'attendre ou de contacter cette personne. view_page.noPublishedVersion=Il n'y a pas de version publi\u00e9e pour cette page. ##Messages message.confirmTitle=Attention ! message.confirmRemoveTopic=confirmRemoveTopic message.accessDenied.create.requiresAuthentification= Veuillez vous authentifier afin de cr\u00e9er une page wiki message.accessDenied.modify.requiresAuthentification= Veuillez vous authentifier afin de modifier une page wiki message.accessDenied.pageNotExists=La page wiki n'existe pas message.accessDenied.pageAlreadyExists=La page wiki existe d\u00e9j\u00e0 message.confirmDelete=Etes vous s\u00fbr de vouloir supprimer cette page et tous ses \u00e9l\u00e9ments associ\u00e9s ( illustrations, historique, ...) ? message.accessDenied.userNotInRole=Vous ne disposez pas des autorisations n\u00e9cessaires pour consulter cette page. message.confirmRemoveVersion=Etes vous s\u00fbr de vouloir supprimer cette version de l'historique ? message.version.removed=Version supprim\u00e9e avec succ\u00e8s de l'historique. message.confirmRemoveImage=Etes vous s\u00fbr de vouloir supprimer cette image ? message.image.removed=Image supprim\u00e9e message.authenticationRequired=Le Wiki n\u00e9cessite une authentification via MyLutece !
Veuillez installer ou configurer le syst\u00e8me d'authentification SVP. message.path.hidden=... message.error.name.notNull=Le champ Description est obligatoire. message.error.file.notNull=Le champ Fichier est obligatoire. message.cancelBy=Publication annul\u00e9e par search_wiki.title=R\u00e9sultats de la recherche search_wiki.search=Termes recherch\u00e9s search_wiki.labelItemsPerPage=Nombre de r\u00e9sultats par page history_page.explanation=S\u00e9lectionner les versions \u00e0 comparer et cliquer sur Modifications pour afficher le d\u00e9tail des diff\u00e9rences. history_page.tableHeader.mostRecent=plus r\u00e9cente history_page.tableHeader.lessRecent=moins r\u00e9cente history_page.tableHeader.date=Date de la modification history_page.tableHeader.author=Auteur history_page.tableHeader.comment=Commentaire \ No newline at end of file diff --git a/src/java/fr/paris/lutece/plugins/wiki/search/WikiIndexer.java b/src/java/fr/paris/lutece/plugins/wiki/search/WikiIndexer.java index 2da02844..f84ed041 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/search/WikiIndexer.java +++ b/src/java/fr/paris/lutece/plugins/wiki/search/WikiIndexer.java @@ -241,10 +241,15 @@ public static Document getDocument( Topic topic, String strUrl, String strLangua // tokenized prior to indexing. String strIdSubject = String.valueOf( topic.getPageName( ) ); doc.add( new Field( SearchItem.FIELD_UID, strIdSubject + "_" + SHORT_NAME_TOPIC, ftNotStored ) ); - TopicVersion latestTopicVersion = TopicVersionHome.findLastVersion( topic.getIdTopic( ) ); String strWikiContent = latestTopicVersion.getWikiContent( strLanguage ).getWikiContent( ); - String strWikiResult = new LuteceWikiParser( strWikiContent, topic.getPageName( ), null, strLanguage ).toString( ); + String strWikiResult = ""; + if ( latestTopicVersion.getWikiContent( strLanguage ).getHtmlWikiContent() != null ) { + strWikiResult = latestTopicVersion.getWikiContent( strLanguage ).getHtmlWikiContent( ); + } else + { + strWikiResult = new LuteceWikiParser( strWikiContent, topic.getPageName( ), null, strLanguage ).toString( ); + } doc.add( new Field( SearchItem.FIELD_CONTENTS, strWikiResult, TextField.TYPE_NOT_STORED ) ); diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/ContentDeserializer.java b/src/java/fr/paris/lutece/plugins/wiki/service/ContentDeserializer.java new file mode 100644 index 00000000..75f3fe25 --- /dev/null +++ b/src/java/fr/paris/lutece/plugins/wiki/service/ContentDeserializer.java @@ -0,0 +1,92 @@ +package fr.paris.lutece.plugins.wiki.service; + +import fr.paris.lutece.portal.service.util.AppLogService; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; + +public class ContentDeserializer { + private static final long serialVersionUID = -2287035947644920508L; + + public Integer topicVersion ; + public String parentPageName; + public int topicId; + public String topicTitle; + + public String topicContent; + + public String language; + + public String wikiHtmlContent; + + public String wikiPageUrl; + public String editComment; + + public String viewRole; + + public String editRole; + + public String topicPageName; + + /** + * Returns the content of the file + * + * The HTTP request + * The HTTP response + * @throws IOException + * If an error occurs + */ + public Integer getTopicVersion() { + return topicVersion; + } + public int getTopicId() { + return topicId; + } + + public String getTopicTitle() { + return topicTitle; + } + + public String getTopicContent() { + return topicContent; + } + + public String getParentPageName() { + return parentPageName; + } + + public String getLanguage() { + return language; + } + + public String getWikiHtmlContent() { + return wikiHtmlContent; + } + + public String getWikiPageUrl() {return wikiPageUrl;} + public String getEditComment() { + return editComment; + } + public String getViewRole() { + return viewRole; + } + public String getEditRole() { + return editRole; + } + public String getTopicPageName() { + return topicPageName; + } + + + + + public static ContentDeserializer deserializeWikiContent(String requestBody) { + ObjectMapper mapper = new ObjectMapper(); + ContentDeserializer contentDeserializer = null; + try { + contentDeserializer = mapper.readValue(requestBody, ContentDeserializer.class); + } catch (IOException e) { + AppLogService.error("Error deserializing wiki content", e); + } + return contentDeserializer; + } +} diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/DiffService.java b/src/java/fr/paris/lutece/plugins/wiki/service/DiffService.java index 71d6aa89..f49ef8c5 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/DiffService.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/DiffService.java @@ -43,7 +43,6 @@ import org.outerj.daisy.diff.html.HtmlSaxDiffOutput; import org.outerj.daisy.diff.html.TextNodeComparator; import org.outerj.daisy.diff.html.dom.DomTreeBuilder; - import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/PathService.java b/src/java/fr/paris/lutece/plugins/wiki/service/PathService.java index 4730f628..eea9a563 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/PathService.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/PathService.java @@ -65,7 +65,7 @@ public static List getParentTopics( Topic topic ) while ( StringUtils.isNotEmpty( topic.getParentPageName( ) ) && !topic.getPageName( ).equals( strWikiRootPageName ) ) { - topic = TopicHome.findByPrimaryKey( topic.getParentPageName( ) ); + topic = TopicHome.findByPageName( topic.getParentPageName( ) ); if ( topic == null || isTopicInList( topicList, topic ) ) { diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/WikiDiff.java b/src/java/fr/paris/lutece/plugins/wiki/service/WikiDiff.java index 94dffaec..7f2e4bae 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/WikiDiff.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/WikiDiff.java @@ -33,7 +33,7 @@ */ package fr.paris.lutece.plugins.wiki.service; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.io.Serializable; diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/WikiExtendableResourceService.java b/src/java/fr/paris/lutece/plugins/wiki/service/WikiExtendableResourceService.java index 9a165ba3..26855a72 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/WikiExtendableResourceService.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/WikiExtendableResourceService.java @@ -45,7 +45,7 @@ import fr.paris.lutece.portal.service.util.AppPathService; import fr.paris.lutece.util.url.UrlItem; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.util.Locale; diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/WikiService.java b/src/java/fr/paris/lutece/plugins/wiki/service/WikiService.java index 82ab4490..c9408e44 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/WikiService.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/WikiService.java @@ -35,9 +35,10 @@ import fr.paris.lutece.plugins.wiki.business.TopicVersion; import fr.paris.lutece.plugins.wiki.service.parser.LuteceWikiParser; +import fr.paris.lutece.plugins.wiki.service.parser.SpecialChar; import fr.paris.lutece.portal.service.cache.AbstractCacheableService; -import java.util.Locale; -import java.util.regex.Pattern; +import fr.paris.lutece.portal.service.util.AppLogService; + /** * Wiki Service @@ -103,36 +104,26 @@ public String getWikiPage( String strPageName, TopicVersion version, String strP { if ( strPageContent == null ) { - String strContent = version.getWikiContent( strLanguage ).getWikiContent( ); - strPageContent = new LuteceWikiParser( strContent, strPageName, strPageUrl, strLanguage ).toString( ); - putInCache( sbKey.toString( ), strPageContent ); + try { + if (version.getWikiContent(strLanguage).getHtmlWikiContent() != null) { + strPageContent = SpecialChar.renderWiki(version.getWikiContent(strLanguage).getHtmlWikiContent()); + putInCache(sbKey.toString(), strPageContent); + } else { + String strContent = SpecialChar.renderWiki(version.getWikiContent(strLanguage).getWikiContent()); + strPageContent = new LuteceWikiParser(strContent, strPageName, strPageUrl, strLanguage).toString(); + putInCache(sbKey.toString(), strPageContent); + } + } + catch( NullPointerException e ) + { + AppLogService.error( "WikiService.getWikiPage : " + e.getMessage( ), e ); + } + } } return strPageContent; } - /** - * Get the Wiki page in text format - * - * @param strPageName - * The page name - * @param version - * The content version - * @param strLanguage - * The language - * @return The HTML code - */ - public String getPageSource( String strPageName, TopicVersion version, String strLanguage ) - { - String strContent = version.getWikiContent( strLanguage ).getWikiContent( ); - strContent = renderSource( strContent ); - Pattern pattern = Pattern.compile( "^\\s*$", Pattern.MULTILINE ); - strContent = pattern.matcher( strContent ).replaceAll( "
" ); - pattern = Pattern.compile( "^\\s*(.*)\\s*$", Pattern.MULTILINE ); - strContent = pattern.matcher( strContent ).replaceAll( "
$1
" ); - - return strContent; - } /** * Get the Wiki page in HTML format @@ -150,29 +141,4 @@ public String getWikiPage( String strPageName, TopicVersion version, String strL return getWikiPage( strPageName, version, null, strLanguage ); } - /** - * Render the wiki content for the editor (convert special characters) - * - * @param version - * The version - * @param strLanguage - * The Language - * @return The content - */ - public static String renderEditor( TopicVersion version, String strLanguage ) - { - return LuteceWikiParser.renderWiki( version.getWikiContent( strLanguage ).getWikiContent( ) ); - } - - /** - * Render the wiki source content - * - * @param strContent - * The wiki page source - * @return The content - */ - public static String renderSource( String strContent ) - { - return LuteceWikiParser.renderSource( strContent ); - } } diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceHtmlParser.java b/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceHtmlParser.java new file mode 100644 index 00000000..5d38e1e4 --- /dev/null +++ b/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceHtmlParser.java @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2002-2023, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.plugins.wiki.service.parser; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +import java.util.List; + +public class LuteceHtmlParser +{ + private final static String STYLE = "style"; + private final static String WIKI_ALIGN_CONTENT_VAL = "wiki-align-content-val-"; + private final static String SUB_LINK_CONTAINER = "subLinkContainer"; + public static String parseHtml( String htmlFromEditor, String wikiPageUrl, String pageTitle ) + { + htmlFromEditor = SpecialChar.renderWiki( htmlFromEditor ); + Document parser = Jsoup.parse( htmlFromEditor ); + Element doc = parser.body( ); + List headers = doc.select( "h1, h2, h3, h4, h5, h6" ); + for ( Element header : headers ) + { + String headerText = header.text( ); + headerText = headerText.replaceAll( " ", "_" ); + // replace all non-alphanumeric characters with nothing + headerText = headerText.replaceAll( "[^A-Za-z0-9_]", "" ); + headerText = headerText.toLowerCase( ); + header.attr( "id", headerText ); + } + List preElements = doc.select( "pre" ); + for ( Element preElement : preElements ) + { + preElement.attr( STYLE, "background-color: #2f3241" ); + } + doc.select( ".toastui-editor-md-preview-highlight" ).forEach( element -> element.removeClass( "toastui-editor-md-preview-highlight" ) ); + if ( doc.select( ".ProseMirror" ).text( ).contains( WIKI_ALIGN_CONTENT_VAL ) ) + { + String alignmentValue = doc.select( ".ProseMirror" ).text( ).split( WIKI_ALIGN_CONTENT_VAL ) [1].substring( 0, 1 ); + doc.select( ".toastui-editor-contents" ).addClass( WIKI_ALIGN_CONTENT_VAL + alignmentValue ); + } + Element toc = doc.select( ".toc" ).first( ); + if ( toc != null ) + { + Element tableOfContent = createTableOfContent( doc, wikiPageUrl, pageTitle ); + doc.select( ".toc" ).remove( ); + + Element flexDiv = new Element( "div" ); + flexDiv.addClass( "wiki-nav-content-wrapper" ); + flexDiv.appendChild( tableOfContent ); + Element contentDiv = new Element( "div" ); + contentDiv.append( parser.body( ).outerHtml( ) ); + flexDiv.appendChild( contentDiv ); + doc = flexDiv; + + return SpecialChar.reverseRender( doc.outerHtml( ) ); + } + else + { + Element contentDiv = new Element( "div" ); + contentDiv.append( parser.body( ).outerHtml( ) ); + return SpecialChar.reverseRender( contentDiv.outerHtml( ) ); + } + } + + public static Element createTableOfContent( Element doc, String wikiPageUrl, String pageTitle ) + { + Element tableOfContent = new Element( "ul" ); + tableOfContent.addClass( "nav" ); + tableOfContent.addClass( "flex-column" ); + tableOfContent.addClass( "wiki-topic-nav" ); + Element titleElement = new Element( "a" ); + titleElement.addClass( "nav-link" ); + titleElement.attr( "href", wikiPageUrl ); + titleElement.attr( STYLE, "font-weight: bold; font-size: 1.5rem;" ); + titleElement.text( pageTitle ); + tableOfContent.appendChild( titleElement ); + List headers = doc.select( "h1, h2, h3" ); + for ( int i = 0; i < headers.size( ); i++ ) + { + Element header = headers.get( i ); + String headerText = header.text( ); + String headerLevel = header.tagName( ); + Element linkElement = new Element( "a" ); + linkElement.attr( "href", wikiPageUrl + "#" + header.id( ) ); + linkElement.addClass( "nav-link" ); + linkElement.text( headerText ); + Element navItem = new Element( "li" ); + if ( headerLevel.equals( "h1" ) ) + { + navItem.addClass( "nav-item" ); + linkElement.attr( STYLE, "font-weight: bold;" ); + if ( i + 1 < headers.size( ) ) + { + if ( headers.get( i + 1 ).tagName( ).equals( "h1" ) ) + { + tableOfContent.appendChild( linkElement ); + } + else + if ( headers.get( i + 1 ).tagName( ).equals( "h2" ) || headers.get( i + 1 ).tagName( ).equals( "h3" ) ) + { + Element divContainer = new Element( "div" ); + divContainer.attr( STYLE, "display: flex; flex-direction: row; spacing: 5px;" ); + divContainer.appendChild( linkElement ); + navItem.appendChild( divContainer ); + tableOfContent.appendChild( navItem ); + Element subLinkContainer = new Element( "ul" ); + subLinkContainer.addClass( SUB_LINK_CONTAINER ); + tableOfContent.appendChild( subLinkContainer ); + } + else + { + tableOfContent.appendChild( linkElement ); + } + } + } + if ( headerLevel.equals( "h2" ) || headerLevel.equals( "h3" ) ) + { + List subLinkContainers = tableOfContent.getElementsByClass( SUB_LINK_CONTAINER ); + if ( subLinkContainers.isEmpty( ) ) + { + Element subLinkContainer = new Element( "ul" ); + subLinkContainer.addClass( SUB_LINK_CONTAINER ); + subLinkContainer.appendChild( linkElement ); + tableOfContent.appendChild( subLinkContainer ); + } + else + { + Element subLinkContainer = subLinkContainers.get( subLinkContainers.size( ) - 1 ); + subLinkContainer.appendChild( linkElement ); + } + } + } + return tableOfContent; + } + +} diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceWikiParser.java b/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceWikiParser.java index 7a2f34b9..4c5f6c3c 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceWikiParser.java +++ b/src/java/fr/paris/lutece/plugins/wiki/service/parser/LuteceWikiParser.java @@ -41,11 +41,12 @@ import fr.paris.lutece.plugins.wiki.business.TopicVersionHome; import fr.paris.lutece.plugins.wiki.business.WikiContent; import fr.paris.lutece.plugins.wiki.service.PathService; -import fr.paris.lutece.plugins.wiki.web.Constants; import fr.paris.lutece.portal.service.spring.SpringContextService; import fr.paris.lutece.portal.service.util.AppLogService; import fr.paris.lutece.portal.service.util.AppPathService; import static ys.wikiparser.Utils.*; +import fr.paris.lutece.plugins.wiki.web.Constants; + import ys.wikiparser.WikiParser; @@ -88,9 +89,8 @@ public LuteceWikiParser( String strWikiText, String strPageName, String strPageU setTableClass( _options.getTableClass( ) ); setParentTableClass( _options.getParentTableClass( ) ); setTocClass( _options.getTocClass( ) ); - parse( renderWiki( strWikiText ) ); + parse( SpecialChar.renderWiki( strWikiText ) ); } - /** * Render specific HTML entities * @@ -110,43 +110,8 @@ private String renderSpecific( String strHTML ) return strRender; } - /** - * Render specific entities - * - * @param strSource - * The source - * @return The source transformed - */ - public static String renderWiki( String strSource ) - { - String strRender = strSource; - strRender = strRender.replaceAll( "\\[lt;", "<" ); - strRender = strRender.replaceAll( "\\[gt;", ">" ); - strRender = strRender.replaceAll( "\\[nbsp;", " " ); - strRender = strRender.replaceAll( "\\[quot;", "\"" ); - strRender = strRender.replaceAll( "\\[amp;", "&" ); - strRender = strRender.replaceAll( "\\[hashmark;", "#" ); - return strRender; - } - /** - * Render specific entities - * - * @param strSource - * The source - * @return The source transformed - */ - public static String renderSource( String strSource ) - { - String strRender = strSource; - strRender = strRender.replaceAll( "\\[lt;", "<" ); - strRender = strRender.replaceAll( "\\[gt;", ">" ); - strRender = strRender.replaceAll( "\\[nbsp;", " " ); - strRender = strRender.replaceAll( "\\[quot;", """ ); - strRender = strRender.replaceAll( "\\[amp;", "&" ); - strRender = strRender.replaceAll( "\\[hashmark;", "#" ); - return strRender; - } + /** * {@inheritDoc } @@ -173,7 +138,7 @@ protected void appendImage( String strText ) int nImageId = Integer.parseInt( link [0].trim( ) ); - Topic topic = TopicHome.findByPrimaryKey( _strPageName ); + Topic topic = TopicHome.findByPageName( _strPageName ); Image image = ImageHome.findByPrimaryKey( nImageId ); if ( image == null || image.getTopicId( ) != topic.getIdTopic( ) ) @@ -258,7 +223,7 @@ protected void appendLink( String strText ) } else { - Topic topic = TopicHome.findByPrimaryKey( escapeHTML( escapeURL( link [0] ) ) ); + Topic topic = TopicHome.findByPageName( escapeHTML( escapeURL( link [0] ) ) ); String strAction; String strAdditionalParameter = ""; String strColorBegin = ""; @@ -313,7 +278,7 @@ protected void appendMacro( String strText ) { sb.append( "

" ); - Topic topic = TopicHome.findByPrimaryKey( _strPageName ); + Topic topic = TopicHome.findByPageName( _strPageName ); List topicList = PathService.getParentTopics( topic ); for ( Topic item : topicList ) diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/parser/SpecialChar.java b/src/java/fr/paris/lutece/plugins/wiki/service/parser/SpecialChar.java new file mode 100644 index 00000000..09afad35 --- /dev/null +++ b/src/java/fr/paris/lutece/plugins/wiki/service/parser/SpecialChar.java @@ -0,0 +1,44 @@ +package fr.paris.lutece.plugins.wiki.service.parser; + +public class SpecialChar { + + /** + * Render specific entities + * + * @param strSource + * The source + * @return The source transformed + */ + public static String renderWiki( String strSource ) + { + String strRender = strSource; + strRender = strRender.replaceAll("\\[@MarkdownLanguage;", ""); + strRender = strRender.replaceAll( "\\[lt;", "<" ); + strRender = strRender.replaceAll( "\\[gt;", ">" ); + strRender = strRender.replaceAll( "\\[nbsp;", " " ); + strRender = strRender.replaceAll( "\\[quot;", "'" ); + strRender = strRender.replaceAll( "\\[amp;", "&" ); + strRender = strRender.replaceAll( "\\[hashmark;", "#" ); + strRender = strRender.replaceAll("\\[codeQuote;", "`"); + strRender = strRender.replaceAll("\\[simpleQuote;", "'"); + return strRender; + } + public static String reverseRender ( String str ) + { + + str = str.replaceAll("<", "\\[lt;"); + str = str.replaceAll(">", "\\[gt;"); + str = str.replaceAll(" ", "\\[nbsp;"); + str = str.replaceAll("'", "\\[quot;"); + str = str.replaceAll("&", "\\[amp;"); + str = str.replaceAll("#", "\\[hashmark;"); + str = str.replaceAll("`", "\\[codeQuote;"); + str = str.replaceAll("'", "\\[simpleQuote;"); + str = str.replaceAll("'", "\\[simpleQuote;"); + str = str.replaceAll("\\\\", ""); + + return str; + } + + +} diff --git a/src/java/fr/paris/lutece/plugins/wiki/service/parser/WikiCreoleToMarkdown.java b/src/java/fr/paris/lutece/plugins/wiki/service/parser/WikiCreoleToMarkdown.java new file mode 100644 index 00000000..a23f5f56 --- /dev/null +++ b/src/java/fr/paris/lutece/plugins/wiki/service/parser/WikiCreoleToMarkdown.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2002-2023, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.plugins.wiki.service.parser; + +import com.vladsch.flexmark.html.HtmlRenderer; +import com.vladsch.flexmark.html2md.converter.FlexmarkHtmlConverter; +import com.vladsch.flexmark.util.data.MutableDataSet; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import java.util.Arrays; +import java.util.List; + +public class WikiCreoleToMarkdown +{ + + public static String renderCustomContent( String str ) + { + str = str.replaceAll( "\\\\", "" ); + str = str.replaceAll( "\\[lt;", "<" ); + str = str.replaceAll( "\\[gt;", ">" ); + str = str.replaceAll( "\\[nbsp;", " " ); + str = str.replaceAll( "\\[quot;", "'" ); + str = str.replaceAll( "\\[amp;", "&" ); + str = str.replaceAll( "\\[hashmark;", "#" ); + str = str.replaceAll( "\\[codeQuote;", "`" ); + str = str.replaceAll( "\\[simpleQuote;", "'" ); + str = str.replaceAll( "badge badge-", "badge badge-badge bg-" ); + str = str.replaceAll( "label label-", "badge badge-badge bg-" ); + str = str.replaceAll( "glyphicon glyphicon-warning-sign", "fa fa-exclamation-triangle" ); + str = str.replaceAll( "glyphicon glyphicon-info-sign", "fa fa-info-circle" ); + str = str.replaceAll( "glyphicon glyphicon-question-sign", "fa fa-question-circle" ); + str = str.replaceAll( "glyphicon glyphicon-ok-sign", "fa fa-check-circle" ); + str = str.replaceAll( "glyphicon glyphicon-remove-sign", "fa fa-times-circle" ); + str = str.replaceAll( "glyphicon glyphicon-chevron-right", "fa fa-chevron-right" ); + str = str.replaceAll( "glyphicon glyphicon-chevron-left", "fa fa-chevron-left" ); + str = str.replaceAll( "glyphicon glyphicon-chevron-up", "fa fa-chevron-up" ); + return str; + } + + public static String wikiCreoleToMd( String strWikiText, String strPageName, String strPageUrl, String strLanguage ) + { + + String htmlContent = new LuteceWikiParser( strWikiText, strPageName, strPageUrl, strLanguage ).toString( ); + + Document htmlDocument = Jsoup.parse( htmlContent ); + Element docBody = htmlDocument.body( ); + List elements = docBody.getAllElements( ); + for ( int i = 0; i < elements.size( ); i++ ) + { + Element element = elements.get( i ); + if ( element.className( ).equals( "well" ) ) + { + String toc = "$$span" + " " + "" + " " + "$$"; + toc = SpecialChar.reverseRender( toc ); + docBody.prepend( toc ); + + } + else + if ( element.className( ).equals( "jumbotron" ) ) + { + Element jumbotron = element; + String jumbotronTitle = jumbotron.select( "h1" ).text( ); + String jumbotronText = jumbotron.select( "p" ).text( ); + Element container = new Element( "span" ); + container.attr( "class", "h-100 p-5 text-bg-light rounded-3" ); + container.attr( "style", "display: block;" ); + if ( jumbotron.select( "img" ).size( ) > 0 ) + { + Element img = jumbotron.select( "img" ).first( ); + Element figure = new Element( "figure" ); + figure.attr( "class", "figure" ); + figure.appendChild( img ); + container.appendChild( figure ); + } + container.appendChild( new Element( "h1" ).attr( "class", "text-dark" ).text( jumbotronTitle ) ); + container.appendChild( new Element( "p" ).attr( "class", "text-muted" ).text( jumbotronText ) ); + String bootStrap5Jumbotron = "$$span\n" + container.toString( ) + "\n$$"; + bootStrap5Jumbotron = SpecialChar.reverseRender( bootStrap5Jumbotron ); + Element p = new Element( "p" ); + p.text( bootStrap5Jumbotron ); + jumbotron.replaceWith( p ); + + } + else + if ( !element.className( ).isEmpty( ) ) + { + String [ ] classNamesToSkip = { + "null", "table", "tbody", "thead", "tr", "td", "th" + }; + if ( Arrays.asList( classNamesToSkip ).contains( element.className( ) ) ) + { + i++; + } + else + { + if ( element.parent( ).tagName( ).equals( "p" ) ) + { + int subDivClassToSkip = element.parent( ).children( ).size( ); + String parent = element.parent( ).outerHtml( ); + String customElement = SpecialChar.reverseRender( parent.toString( ) ); + customElement = "$$span" + customElement + "$$"; + Element p = new Element( "p" ); + p.text( customElement ); + element.parent( ).replaceWith( p ); + i = i + subDivClassToSkip - 1; + } + else + { + String customElement = SpecialChar.reverseRender( element.outerHtml( ).toString( ) ); + customElement = "$$span" + customElement + "$$"; + Element p = new Element( "p" ); + p.text( customElement ); + element.replaceWith( p ); + } + + } + } + else + if ( element.tagName( ).equals( "img" ) ) + { + Boolean imgContainsAttributes = element.hasAttr( "class" ) && !element.className( ).isEmpty( ) + || element.hasAttr( "width" ) && element.getElementsByAttribute( "width" ).size( ) > 0 + || element.hasAttr( "height" ) && element.getElementsByAttribute( "height" ).size( ) > 0 + || element.hasAttr( "align" ) && element.getElementsByAttribute( "align" ).size( ) > 0; + if ( element.parent( ).tagName( ).equals( "p" ) ) + { + String parent = element.parent( ).outerHtml( ); + String customElement = SpecialChar.reverseRender( parent.toString( ) ); + customElement = "$$span" + customElement + "$$"; + Element p = new Element( "p" ); + p.text( customElement ); + element.parent( ).replaceWith( p ); + } + else + if ( imgContainsAttributes ) + { + String customElement = SpecialChar.reverseRender( element.outerHtml( ).toString( ) ); + customElement = "$$span" + customElement + "$$"; + Element p = new Element( "p" ); + p.text( customElement ); + element.replaceWith( p ); + } + } + } + + MutableDataSet options = new MutableDataSet( ); + + options.set( HtmlRenderer.HARD_BREAK, "
\n" ); + options.set( FlexmarkHtmlConverter.BR_AS_PARA_BREAKS, false ); + options.set( FlexmarkHtmlConverter.OUTPUT_ATTRIBUTES_ID, false ); + options.set( FlexmarkHtmlConverter.BR_AS_EXTRA_BLANK_LINES, false ); + String markdown = FlexmarkHtmlConverter.builder( options ).build( ).convert( docBody.toString( ) ); + markdown = renderCustomContent( markdown ); + String newMarkdown = ""; + + for ( String line : markdown.split( System.lineSeparator( ) ) ) + { + if ( line.contains( "$$span" ) ) + { + line = line.replace( "$$span", "" ); + line = line.replace( "$$", "" ); + String reFormatedLine = System.lineSeparator( ) + "$$span" + System.lineSeparator( ) + line + System.lineSeparator( ) + "$$" + + System.lineSeparator( ); + newMarkdown += reFormatedLine; + } + else + { + newMarkdown += line + System.lineSeparator( ); + } + } + return newMarkdown; + } + +} diff --git a/src/java/fr/paris/lutece/plugins/wiki/utils/auth/WikiAnonymousUser.java b/src/java/fr/paris/lutece/plugins/wiki/utils/auth/WikiAnonymousUser.java index bd136a05..d6fd451c 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/utils/auth/WikiAnonymousUser.java +++ b/src/java/fr/paris/lutece/plugins/wiki/utils/auth/WikiAnonymousUser.java @@ -34,6 +34,10 @@ package fr.paris.lutece.plugins.wiki.utils.auth; import fr.paris.lutece.portal.service.security.LuteceUser; +import fr.paris.lutece.portal.service.security.SecurityService; +import fr.paris.lutece.portal.service.security.UserNotSignedException; + +import javax.servlet.http.HttpServletRequest; /** * WikiAnonymousUser @@ -47,4 +51,34 @@ public WikiAnonymousUser( ) { super( "Anonymous", new WikiAnonymousAuthentication( ) ); } + + /** + * Checks the connected user + * + * @param request + * The HTTP request + * @return The user + * @throws UserNotSignedException + * if user not connected + */ + public static LuteceUser checkUser(HttpServletRequest request) throws UserNotSignedException + { + LuteceUser user; + + if ( SecurityService.isAuthenticationEnable( ) ) + { + user = SecurityService.getInstance( ).getRemoteUser( request ); + + if ( user == null ) + { + throw new UserNotSignedException( ); + } + } + else + { + user = new WikiAnonymousUser( ); + } + + return user; + } } diff --git a/src/java/fr/paris/lutece/plugins/wiki/web/Constants.java b/src/java/fr/paris/lutece/plugins/wiki/web/Constants.java index 8b84cbb6..13c1c1de 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/web/Constants.java +++ b/src/java/fr/paris/lutece/plugins/wiki/web/Constants.java @@ -7,7 +7,7 @@ * are met: * * 1. Redistributions of source code must retain the above copyright notice - * and the following disclaimer. + * and the following discœimer. * * 2. Redistributions in binary form must reproduce the above copyright notice * and the following disclaimer in the documentation and/or other materials @@ -50,7 +50,11 @@ public final class Constants public static final String PARAMETER_ACTION = "action"; public static final String PARAMETER_CONTENT = "content"; public static final String PARAMETER_MODIFICATION_COMMENT = "modification_comment"; + public static final String PARAMETER_HTML_CONTENT = "wiki_html_content"; + public static final String PARAMETER_LOCAL = "locale"; public static final String PARAMETER_PREVIOUS_VERSION_ID = "previous_version_id"; + public static final String PARAMETER_TOPIC_VERSION_ID = "id_topic_version"; + public static final String PARAMETER_TOPIC_ID = "topic_id"; public static final String PARAMETER_NEW_VERSION = "new_version"; public static final String PARAMETER_OLD_VERSION = "old_version"; @@ -64,10 +68,18 @@ public final class Constants public static final String PARAMETER_IMAGE_NAME = "image_name"; public static final String PARAMETER_IMAGE_FILE = "image_file"; public static final String PARAMETER_IMAGE_ID = "id_image"; - public static final String PARAMETER_TOPIC_VERSION_ID = "id_topic_version"; + public static final String PARAMETER_CREATE_NEW_VERSION = "create_version"; + public static final String PARAMETER_PUBLISH = "publish_version"; public static final String MESSAGE_PAGE_NOT_EXISTS = "wiki.message.accessDenied.pageNotExists"; public static final String MESSAGE_PAGE_ALREADY_EXISTS = "wiki.message.accessDenied.pageAlreadyExists"; public static final String MESSAGE_USER_NOT_IN_ROLE = "wiki.message.accessDenied.userNotInRole"; + public static final String PARENT_PAGE_NAME_IS_NULL = "none"; + public static final String MARKDOWN_TAG = "[@MarkdownLanguage;"; + public static final String PARAMETER_USER_NAME = "user_name"; + public static final String MESSAGE_CANCELED_BY = "wiki.message.cancelBy"; + + public static final String PARAMETER_VIEW_DIFF_HTML = "view_diff_html"; + /** Private constructor */ private Constants( ) diff --git a/src/java/fr/paris/lutece/plugins/wiki/web/WikiApp.java b/src/java/fr/paris/lutece/plugins/wiki/web/WikiApp.java index f476bd54..52c23c20 100644 --- a/src/java/fr/paris/lutece/plugins/wiki/web/WikiApp.java +++ b/src/java/fr/paris/lutece/plugins/wiki/web/WikiApp.java @@ -33,6 +33,8 @@ */ package fr.paris.lutece.plugins.wiki.web; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import fr.paris.lutece.plugins.avatar.service.AvatarService; import fr.paris.lutece.plugins.wiki.business.Image; import fr.paris.lutece.plugins.wiki.business.ImageHome; @@ -41,15 +43,12 @@ import fr.paris.lutece.plugins.wiki.business.TopicVersion; import fr.paris.lutece.plugins.wiki.business.TopicVersionHome; import fr.paris.lutece.plugins.wiki.business.WikiContent; -import fr.paris.lutece.plugins.wiki.service.DiffService; -import fr.paris.lutece.plugins.wiki.service.RoleService; -import fr.paris.lutece.plugins.wiki.service.WikiLocaleService; -import fr.paris.lutece.plugins.wiki.service.WikiService; -import fr.paris.lutece.plugins.wiki.service.WikiUtils; -import fr.paris.lutece.plugins.wiki.service.parser.LuteceWikiParser; +import fr.paris.lutece.plugins.wiki.service.*; +import fr.paris.lutece.plugins.wiki.service.parser.LuteceHtmlParser; +import fr.paris.lutece.plugins.wiki.service.parser.SpecialChar; +import fr.paris.lutece.plugins.wiki.service.parser.WikiCreoleToMarkdown; import fr.paris.lutece.plugins.wiki.utils.auth.WikiAnonymousUser; import fr.paris.lutece.portal.business.page.Page; -import fr.paris.lutece.portal.business.role.RoleHome; import fr.paris.lutece.portal.service.content.XPageAppService; import fr.paris.lutece.portal.service.datastore.DatastoreService; import fr.paris.lutece.portal.service.i18n.I18nService; @@ -65,7 +64,7 @@ import fr.paris.lutece.portal.service.security.SecurityService; import fr.paris.lutece.portal.service.security.UserNotSignedException; import fr.paris.lutece.portal.service.spring.SpringContextService; -import fr.paris.lutece.portal.service.template.AppTemplateService; +import fr.paris.lutece.portal.service.util.AppLogService; import fr.paris.lutece.portal.service.util.AppPathService; import fr.paris.lutece.portal.service.util.AppPropertiesService; import fr.paris.lutece.portal.util.mvc.commons.annotations.Action; @@ -78,26 +77,16 @@ import fr.paris.lutece.portal.web.xpages.XPage; import fr.paris.lutece.util.ReferenceItem; import fr.paris.lutece.util.ReferenceList; -import fr.paris.lutece.util.html.HtmlTemplate; import fr.paris.lutece.util.html.Paginator; import fr.paris.lutece.util.url.UrlItem; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; + +import java.io.*; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; + import org.apache.commons.fileupload.FileItem; -import org.apache.commons.lang.StringUtils; -import org.bouncycastle.i18n.LocaleString; +import org.apache.commons.lang3.StringUtils; /** * This class provides a simple implementation of an XPage @@ -106,14 +95,12 @@ public class WikiApp extends MVCApplication { private static final String TEMPLATE_MODIFY_WIKI = "skin/plugins/wiki/modify_page.html"; - private static final String TEMPLATE_PREVIEW_WIKI = "skin/plugins/wiki/preview_page.html"; private static final String TEMPLATE_VIEW_WIKI = "skin/plugins/wiki/view_page.html"; private static final String TEMPLATE_VIEW_HISTORY_WIKI = "skin/plugins/wiki/history_page.html"; private static final String TEMPLATE_VIEW_DIFF_TOPIC_WIKI = "skin/plugins/wiki/diff_topic.html"; private static final String TEMPLATE_LIST_WIKI = "skin/plugins/wiki/list_wiki.html"; private static final String TEMPLATE_MAP_WIKI = "skin/plugins/wiki/map_wiki.html"; private static final String TEMPLATE_SEARCH_WIKI = "skin/plugins/wiki/search_wiki.html"; - private static final String BEAN_SEARCH_ENGINE = "wiki.wikiSearchEngine"; private static final String PROPERTY_PAGE_PATH = "wiki.pagePathLabel"; @@ -128,15 +115,13 @@ public class WikiApp extends MVCApplication private static final String MARK_TOPIC = "topic"; private static final String MARK_TOPIC_TITLE = "topic_title"; - private static final String MARK_TOPIC_NAME = "topic_name"; - private static final String MARK_TOPIC_CONTENT_HTML = "topic_content_html"; private static final String MARK_REFLIST_TOPIC = "reflist_topic"; private static final String MARK_MAP_TOPIC_TITLE = "map_topic_title"; private static final String MARK_MAP_TOPIC_CHILDREN = "map_topic_children"; private static final String MARK_WIKI_ROOT_PAGE_NAME = "wiki_root_page_name"; + private static final String MARK_VERSION = "version"; private static final String MARK_LATEST_VERSION = "lastVersion"; - private static final String MARK_DIFF_HTML = "diff_html"; - private static final String MARK_DIFF_SOURCE = "diff_source"; + private static final String MARK_DIFF = "diff"; private static final String MARK_RESULT = "result"; private static final String MARK_LIST_TOPIC_VERSION = "listTopicVersion"; private static final String MARK_PAGE_ROLES_LIST = "page_roles_list"; @@ -148,7 +133,6 @@ public class WikiApp extends MVCApplication private static final String MARK_EXTEND = "isExtendInstalled"; private static final String MARK_LANGUAGES_LIST = "languages_list"; private static final String MARK_CURRENT_LANGUAGE = "current_language"; - private static final String PARAMETER_LANGUAGE = "language"; private static final String VIEW_HOME = "home"; @@ -161,26 +145,20 @@ public class WikiApp extends MVCApplication private static final String VIEW_SEARCH = "search"; private static final String VIEW_DIFF = "diff"; private static final String VIEW_LIST_IMAGES = "listImages"; - private static final String ACTION_NEW_PAGE = "newPage"; - private static final String ACTION_MODIFY_PAGE = "modifyPage"; private static final String ACTION_DELETE_PAGE = "deletePage"; private static final String ACTION_REMOVE_IMAGE = "removeImage"; - private static final String ACTION_CONFIRM_REMOVE_IMAGE = "confirmRemoveImage"; private static final String ACTION_REMOVE_VERSION = "removeVersion"; private static final String ACTION_CONFIRM_REMOVE_VERSION = "confirmRemoveVersion"; private static final String ACTION_UPLOAD_IMAGE = "uploadImage"; - private static final String ACTION_CHANGE_LANGUAGE = "changeLanguage"; - private static final String MESSAGE_IMAGE_REMOVED = "wiki.message.image.removed"; - private static final String MESSAGE_CONFIRM_REMOVE_IMAGE = "wiki.message.confirmRemoveImage"; private static final String MESSAGE_NAME_MANDATORY = "wiki.message.error.name.notNull"; private static final String MESSAGE_FILE_MANDATORY = "wiki.message.error.file.notNull"; private static final String MESSAGE_CONFIRM_REMOVE_VERSION = "wiki.message.confirmRemoveVersion"; private static final String MESSAGE_VERSION_REMOVED = "wiki.message.version.removed"; private static final String MESSAGE_AUTHENTICATION_REQUIRED = "wiki.message.authenticationRequired"; private static final String MESSAGE_PATH_HIDDEN = "wiki.message.path.hidden"; - + private static final String MESSAGE_NO_PUBLISHED_VERSION = "wiki.view_page.noPublishedVersion"; private static final String ANCHOR_IMAGES = "#images"; private static final String DSKEY_WIKI_ROOT_LABEL = "wiki.site_property.path.rootLabel"; @@ -224,7 +202,7 @@ public XPage getHome( HttpServletRequest request ) /** * Gets list page of all wiki pages - * + * * @param request * The HTTP request * @return The page @@ -255,7 +233,7 @@ public XPage getTopicsList( HttpServletRequest request ) /** * Gets maps page of the wiki - * + * * @param request * The HTTP request * @return The page @@ -362,20 +340,27 @@ public XPage getTopic( HttpServletRequest request ) throws SiteMessageException, String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); Topic topic = getTopic( request, strPageName, MODE_VIEW ); TopicVersion version = TopicVersionHome.findLastVersion( topic.getIdTopic( ) ); + String strWikiPage = null; + String topicTitle = getTopicTitle( request, topic ); if ( version == null ) { - UrlItem url = new UrlItem( AppPathService.getBaseUrl( request ) + AppPathService.getPortalUrl( ) ); - url.addParameter( Constants.PARAMETER_PAGE, Constants.PLUGIN_NAME ); - url.addParameter( Constants.PARAMETER_ACTION, ACTION_NEW_PAGE ); - url.addParameter( Constants.PARAMETER_PAGE_NAME, strPageName ); - return redirect( request, url.getUrl( ) ); + strWikiPage = I18nService.getLocalizedString( MESSAGE_NO_PUBLISHED_VERSION, getLocale( request ) ); + } + else + { + fillUserData( version ); + strWikiPage = WikiService.instance( ).getWikiPage( strPageName, version, getPageUrl( request ), getLanguage( request ) ); + if ( version.getWikiContent( getLanguage( request ) ).getPageTitle( ) != null + && !version.getWikiContent( getLanguage( request ) ).getPageTitle( ).isEmpty( ) ) + { + // if the page title is not empty, we use it instead of the topic title + topicTitle = version.getWikiContent( getLanguage( request ) ).getPageTitle( ); + } } - fillUserData( version ); - String strWikiPage = WikiService.instance( ).getWikiPage( strPageName, version, getPageUrl( request ), getLanguage( request ) ); Map model = getModel( ); model.put( MARK_RESULT, strWikiPage ); model.put( MARK_TOPIC, topic ); - model.put( MARK_TOPIC_TITLE, getTopicTitle( request, topic ) ); + model.put( MARK_TOPIC_TITLE, topicTitle ); model.put( MARK_LATEST_VERSION, version ); model.put( MARK_EDIT_ROLE, RoleService.hasEditRole( request, topic ) ); model.put( MARK_ADMIN_ROLE, RoleService.hasAdminRole( request ) ); @@ -385,7 +370,6 @@ public XPage getTopic( HttpServletRequest request ) throws SiteMessageException, XPage page = getXPage( TEMPLATE_VIEW_WIKI, getLocale( request ), model ); page.setTitle( getPageTitle( getTopicTitle( request, topic ) ) ); page.setExtendedPathLabel( getPageExtendedPath( topic, request ) ); - return page; } @@ -403,14 +387,18 @@ public XPage getTopic( HttpServletRequest request ) throws SiteMessageException, @Action( ACTION_NEW_PAGE ) public XPage doCreateTopic( HttpServletRequest request ) throws UserNotSignedException, UnsupportedEncodingException { - checkUser( request ); + WikiAnonymousUser.checkUser( request ); String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); String strParentPageName = request.getParameter( Constants.PARAMETER_PARENT_PAGE_NAME ); + if ( strParentPageName == null ) + { + strParentPageName = Constants.PARENT_PAGE_NAME_IS_NULL; + } String strPageTitle = strPageName; strPageName = WikiUtils.normalize( strPageName ); - Topic topic = TopicHome.findByPrimaryKey( strPageName ); + Topic topic = TopicHome.findByPageName( strPageName ); if ( topic == null ) { topic = new Topic( ); @@ -421,11 +409,9 @@ public XPage doCreateTopic( HttpServletRequest request ) throws UserNotSignedExc TopicHome.create( topic ); } - Map mapParameters = new ConcurrentHashMap<>( ); mapParameters.put( Constants.PARAMETER_PAGE_NAME, strPageName ); - mapParameters.put( Constants.PARAMETER_PAGE_TITLE, URLEncoder.encode( strPageTitle, "UTF-8" ) ); - + mapParameters.put( Constants.PARAMETER_PAGE_TITLE, strPageTitle ); return redirect( request, VIEW_MODIFY_PAGE, mapParameters ); } @@ -441,10 +427,9 @@ public XPage doCreateTopic( HttpServletRequest request ) throws UserNotSignedExc @View( VIEW_MODIFY_PAGE ) public XPage getModifyTopic( HttpServletRequest request ) throws SiteMessageException, UserNotSignedException { - checkUser( request ); - + WikiAnonymousUser.checkUser( request ); String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); - + Integer nVersion = getVersionTopicVersionId( request ); Topic topic; Topic topicSession = (Topic) request.getSession( ).getAttribute( MARK_TOPIC ); if ( topicSession != null && topicSession.getPageName( ).equals( strPageName ) ) @@ -456,39 +441,53 @@ public XPage getModifyTopic( HttpServletRequest request ) throws SiteMessageExce { topic = getTopic( request, strPageName, MODE_EDIT ); } - - TopicVersion topicVersion; - TopicVersion topicVersionSession = (TopicVersion) request.getSession( ).getAttribute( MARK_LATEST_VERSION ); - if ( topicVersionSession != null && topicVersionSession.getIdTopic( ) == topic.getIdTopic( ) ) - { - topicVersion = topicVersionSession; - request.getSession( ).removeAttribute( MARK_LATEST_VERSION ); + String strLocale = WikiLocaleService.getDefaultLanguage( ); + try { + if( request.getParameter( Constants.PARAMETER_LOCAL ) != null ) + { + strLocale = request.getParameter( Constants.PARAMETER_LOCAL ); + } + } catch (Exception e) { + AppLogService.error("no local parameter local", e); } - else + + TopicVersion topicVersion = TopicVersionHome.findLastVersion( topic.getIdTopic( ) ); + + if ( topicVersion != null ) { - topicVersion = TopicVersionHome.findLastVersion( topic.getIdTopic( ) ); - if ( topicVersion != null ) + WikiContent content = topicVersion.getWikiContent( strLocale ); + + if ( content != null ) { - String strLanguage = getLanguage( request ); - WikiContent content = topicVersion.getWikiContent( strLanguage ); - content.setWikiContent( WikiService.renderEditor( topicVersion, strLanguage ) ); + String markupContent = content.getWikiContent( ); + if ( !markupContent.startsWith( Constants.MARKDOWN_TAG ) ) + { + String url = request.getRequestURL( ).toString( ); + String newMarkdown = WikiCreoleToMarkdown.wikiCreoleToMd( markupContent, strPageName, url, strLocale ); + content.setWikiContent( newMarkdown ); + } + else + { + content.setWikiContent( SpecialChar.renderWiki( markupContent ) ); + } + content.setPageTitle( SpecialChar.renderWiki( content.getPageTitle( ) ) ); + topicVersion.addLocalizedWikiContent( strLocale, content ); } } - + Map model = getModel( ); ReferenceList topicRefList = getTopicsReferenceListForUser( request, true ); topicRefList.removeIf( x -> x.getCode( ).equals( topic.getPageName( ) ) ); - - Map model = getModel( ); + List topicNameList = getTopicNameListForUser( request); model.put( MARK_TOPIC, topic ); - model.put( MARK_LATEST_VERSION, topicVersion ); + model.put( MARK_VERSION, topicVersion ); model.put( MARK_PAGE_ROLES_LIST, RoleService.getUserRoles( request ) ); model.put( MARK_EDIT_ROLE, RoleService.hasEditRole( request, topic ) ); model.put( MARK_ADMIN_ROLE, RoleService.hasAdminRole( request ) ); model.put( MARK_LANGUAGES_LIST, WikiLocaleService.getLanguages( ) ); model.put( MARK_REFLIST_TOPIC, topicRefList ); - + model.put( "locale", strLocale ); + model.put( "topicNameList", topicNameList ); ExtendableResourcePluginActionManager.fillModel( request, null, model, Integer.toString( topic.getIdTopic( ) ), Topic.RESOURCE_TYPE ); - XPage page = getXPage( TEMPLATE_MODIFY_WIKI, request.getLocale( ), model ); page.setTitle( getPageTitle( getTopicTitle( request, topic ) ) ); page.setExtendedPathLabel( getPageExtendedPath( topic, request ) ); @@ -496,63 +495,6 @@ public XPage getModifyTopic( HttpServletRequest request ) throws SiteMessageExce return page; } - /** - * Modifies a wiki page - * - * @param request - * The HTTP Request - * @return The redirect URL - * @throws UserNotSignedException - * If user not connected - */ - @Action( ACTION_MODIFY_PAGE ) - public XPage doModifyTopic( HttpServletRequest request ) throws UserNotSignedException - { - LuteceUser user = checkUser( request ); - - String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); - Topic topic = TopicHome.findByPrimaryKey( strPageName ); - - if ( RoleService.hasEditRole( request, topic ) ) - { - String strPreviousVersionId = request.getParameter( Constants.PARAMETER_PREVIOUS_VERSION_ID ); - String strTopicId = request.getParameter( Constants.PARAMETER_TOPIC_ID ); - String strComment = request.getParameter( Constants.PARAMETER_MODIFICATION_COMMENT ); - String strViewRole = request.getParameter( Constants.PARAMETER_VIEW_ROLE ); - String strEditRole = request.getParameter( Constants.PARAMETER_EDIT_ROLE ); - String strParentPageName = request.getParameter( Constants.PARAMETER_PARENT_PAGE_NAME ); - int nPreviousVersionId = Integer.parseInt( strPreviousVersionId ); - int nTopicId = Integer.parseInt( strTopicId ); - - TopicVersion topicVersion = new TopicVersion( ); - topicVersion.setIdTopic( nTopicId ); - topicVersion.setUserName( user.getName( ) ); - topicVersion.setEditComment( strComment ); - topicVersion.setIdTopicVersionPrevious( nPreviousVersionId ); - for ( String strLanguage : WikiLocaleService.getLanguages( ) ) - { - String strPageTitle = request.getParameter( Constants.PARAMETER_PAGE_TITLE + "_" + strLanguage ); - String strContent = request.getParameter( Constants.PARAMETER_CONTENT + "_" + strLanguage ); - WikiContent content = new WikiContent( ); - content.setPageTitle( strPageTitle ); - content.setWikiContent( strContent ); - topicVersion.addLocalizedWikiContent( strLanguage, content ); - } - - TopicVersionHome.addTopicVersion( topicVersion ); - - topic.setViewRole( strViewRole ); - topic.setEditRole( strEditRole ); - topic.setParentPageName( strParentPageName ); - TopicHome.update( topic ); - } - - Map mapParameters = new ConcurrentHashMap<>( ); - mapParameters.put( Constants.PARAMETER_PAGE_NAME, strPageName ); - - return redirect( request, VIEW_PAGE, mapParameters ); - } - /** * Displays the preview of a wiki page * @@ -563,59 +505,38 @@ public XPage doModifyTopic( HttpServletRequest request ) throws UserNotSignedExc * if an exception occurs */ @View( VIEW_PREVIEW ) - public XPage getPreviewTopic( HttpServletRequest request ) throws SiteMessageException, UserNotSignedException + public XPage getPreviewTopic( HttpServletRequest request ) throws IOException, SiteMessageException, UserNotSignedException { - LuteceUser user = checkUser( request ); - - String strPreviousVersionId = request.getParameter( Constants.PARAMETER_PREVIOUS_VERSION_ID ); - String strTopicId = request.getParameter( Constants.PARAMETER_TOPIC_ID ); - String strComment = request.getParameter( Constants.PARAMETER_MODIFICATION_COMMENT ); - String strViewRole = request.getParameter( Constants.PARAMETER_VIEW_ROLE ); - String strEditRole = request.getParameter( Constants.PARAMETER_EDIT_ROLE ); - String strParentPageName = request.getParameter( Constants.PARAMETER_PARENT_PAGE_NAME ); - int nPreviousVersionId = Integer.parseInt( strPreviousVersionId ); - int nTopicId = Integer.parseInt( strTopicId ); - - TopicVersion topicVersion = new TopicVersion( ); - topicVersion.setIdTopic( nTopicId ); - topicVersion.setUserName( user.getName( ) ); - topicVersion.setEditComment( strComment ); - topicVersion.setIdTopicVersionPrevious( nPreviousVersionId ); - for ( String strLanguage : WikiLocaleService.getLanguages( ) ) + StringBuilder sb = new StringBuilder( ); + BufferedReader reader = request.getReader( ); + String line; + while ( ( line = reader.readLine( ) ) != null ) { - String strPageTitle = request.getParameter( Constants.PARAMETER_PAGE_TITLE + "_" + strLanguage ); - String strContent = request.getParameter( Constants.PARAMETER_CONTENT + "_" + strLanguage ); - WikiContent content = new WikiContent( ); - content.setPageTitle( strPageTitle ); - content.setWikiContent( LuteceWikiParser.renderWiki( strContent ) ); - topicVersion.addLocalizedWikiContent( strLanguage, content ); + sb.append( line ); } - - String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); - Topic topic = TopicHome.findByPrimaryKey( strPageName ); - topic.setViewRole( strViewRole ); - topic.setEditRole( strEditRole ); - topic.setParentPageName( strParentPageName ); - - request.getSession( ).setAttribute( MARK_TOPIC, topic ); - request.getSession( ).setAttribute( MARK_LATEST_VERSION, topicVersion ); - - String strLanguage = getLanguage( request ); - String strContent = request.getParameter( Constants.PARAMETER_CONTENT + "_" + strLanguage ); - String strPageContent = new LuteceWikiParser( strContent, strPageName, null, strLanguage ).toString( ); - String strPageTitle = request.getParameter( Constants.PARAMETER_PAGE_TITLE + "_" + strLanguage ); - - Map model = getModel( ); - model.put( MARK_RESULT, strPageContent ); - model.put( MARK_TOPIC, topic ); - model.put( MARK_LATEST_VERSION, topicVersion ); - model.put( MARK_TOPIC_TITLE, strPageTitle ); - - XPage page = getXPage( TEMPLATE_PREVIEW_WIKI, request.getLocale( ), model ); - page.setTitle( getPageTitle( getTopicTitle( request, topic ) ) ); - page.setExtendedPathLabel( getPageExtendedPath( topic, request ) ); - - return page; + String requestBody = sb.toString( ); + String wikiPageUrl = ""; + String pageTitle = ""; + String htmlContent = ""; + ObjectMapper mapper = new ObjectMapper( ); + HashMap previewContent = new HashMap<>( ); + + try + { + ContentDeserializer newContent = ContentDeserializer.deserializeWikiContent( requestBody ); + WikiAnonymousUser.checkUser( request ); + wikiPageUrl = newContent.getWikiPageUrl( ); + pageTitle = newContent.getTopicTitle( ); + htmlContent = newContent.getWikiHtmlContent( ); + htmlContent = LuteceHtmlParser.parseHtml( htmlContent, wikiPageUrl, pageTitle ); + htmlContent = SpecialChar.renderWiki( htmlContent ); + previewContent.put( "htmlContent", htmlContent ); + } + catch( Exception e ) + { + AppLogService.error( e.getMessage( ), e ); + } + return responseJSON(mapper.writeValueAsString( previewContent)); } /** @@ -634,7 +555,6 @@ public XPage getHistory( HttpServletRequest request ) throws SiteMessageExceptio Topic topic = getTopic( request, strPageName, MODE_VIEW ); Map model = getModel( ); Collection listTopicVersions = TopicVersionHome.findAllVersions( topic.getIdTopic( ) ); - fillUsersData( listTopicVersions ); model.put( MARK_LIST_TOPIC_VERSION, listTopicVersions ); model.put( MARK_TOPIC, topic ); @@ -664,7 +584,11 @@ public XPage getDiff( HttpServletRequest request ) throws SiteMessageException, { String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); Topic topic = getTopic( request, strPageName, MODE_VIEW ); - + Boolean viewDiffHtml = true; + if( request.getParameter( Constants.PARAMETER_VIEW_DIFF_HTML ) != null ) + { + viewDiffHtml = Boolean.parseBoolean( request.getParameter( Constants.PARAMETER_VIEW_DIFF_HTML ) ); + } String strNewVersion = request.getParameter( Constants.PARAMETER_NEW_VERSION ); String strOldVersion = request.getParameter( Constants.PARAMETER_OLD_VERSION ); int nNewTopicVersion = Integer.parseInt( strNewVersion ); @@ -675,16 +599,21 @@ public XPage getDiff( HttpServletRequest request ) throws SiteMessageException, TopicVersion oldTopicVersion = TopicVersionHome.findByPrimaryKey( nPrevTopicVersion ); String strLanguage = getLanguage( request ); - String strNewHtml = WikiService.instance( ).getWikiPage( strPageName, newTopicVersion, strLanguage ); - String strOldHtml = WikiService.instance( ).getWikiPage( strPageName, oldTopicVersion, strLanguage ); - String strNewSource = WikiService.instance( ).getPageSource( strPageName, newTopicVersion, strLanguage ); - String strOldSource = WikiService.instance( ).getPageSource( strPageName, oldTopicVersion, strLanguage ); - String strDiffHtml = DiffService.getDiff( strOldHtml, strNewHtml ); - String strDiffSource = DiffService.getDiff( strOldSource, strNewSource ); - + String strDiff = ""; + if(viewDiffHtml){ + String strNewHtml = WikiService.instance( ).getWikiPage( strPageName, newTopicVersion, strLanguage ); + String strOldHtml = WikiService.instance( ).getWikiPage( strPageName, oldTopicVersion, strLanguage ); + strDiff = DiffService.getDiff( strOldHtml, strNewHtml ); + } else { + String strNewSource = SpecialChar.renderWiki(TopicVersionHome.findByPrimaryKey( nNewTopicVersion ).getWikiContent( strLanguage ).getWikiContent( )); + String strOldSource = SpecialChar.renderWiki(TopicVersionHome.findByPrimaryKey( nPrevTopicVersion ).getWikiContent( strLanguage ).getWikiContent( )); + strDiff = DiffService.getDiff( strOldSource, strNewSource ); + } Map model = getModel( ); - model.put( MARK_DIFF_HTML, strDiffHtml ); - model.put( MARK_DIFF_SOURCE, strDiffSource ); + model.put( Constants.PARAMETER_NEW_VERSION, newTopicVersion.getIdTopicVersion() ); + model.put( Constants.PARAMETER_OLD_VERSION, oldTopicVersion.getIdTopicVersion() ); + model.put( Constants.PARAMETER_VIEW_DIFF_HTML, viewDiffHtml ); + model.put( MARK_DIFF, strDiff ); model.put( MARK_TOPIC, topic ); XPage page = getXPage( TEMPLATE_VIEW_DIFF_TOPIC_WIKI, request.getLocale( ), model ); @@ -693,7 +622,6 @@ public XPage getDiff( HttpServletRequest request ) throws SiteMessageException, return page; } - /** * Deletes a wiki page * @@ -706,23 +634,20 @@ public XPage getDiff( HttpServletRequest request ) throws SiteMessageException, @Action( ACTION_DELETE_PAGE ) public XPage doDeleteTopic( HttpServletRequest request ) throws UserNotSignedException { - checkUser( request ); String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); - Topic topic = TopicHome.findByPrimaryKey( strPageName ); - - // Requires Admin role + Topic topic = TopicHome.findByPageName( strPageName ); if ( RoleService.hasAdminRole( request ) ) { TopicHome.remove( topic.getIdTopic( ) ); } - - return redirectView( request, VIEW_HOME ); + XPage page = redirectView( request, VIEW_MAP ); + return page; } /** * Uploads an image - * + * * @param request * The HTTP request * @return The XPage @@ -732,46 +657,48 @@ public XPage doDeleteTopic( HttpServletRequest request ) throws UserNotSignedExc @Action( ACTION_UPLOAD_IMAGE ) public XPage doUploadImage( HttpServletRequest request ) throws UserNotSignedException { - checkUser( request ); String strPageName = request.getParameter( Constants.PARAMETER_PAGE_NAME ); String strName = request.getParameter( Constants.PARAMETER_IMAGE_NAME ); String strTopicId = request.getParameter( Constants.PARAMETER_TOPIC_ID ); - MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; - FileItem fileItem = multipartRequest.getFile( Constants.PARAMETER_IMAGE_FILE ); - Image image = new Image( ); - boolean bError = false; - - if ( ( fileItem == null ) || ( fileItem.getName( ) == null ) || "".equals( fileItem.getName( ) ) ) - { - bError = true; - addError( MESSAGE_FILE_MANDATORY, request.getLocale( ) ); - } - - if ( ( strName == null ) || strName.trim( ).equals( "" ) ) - { - bError = true; - addError( MESSAGE_NAME_MANDATORY, request.getLocale( ) ); - } - - if ( !bError ) + if ( RoleService.hasAdminRole( request ) ) { - image.setName( strName ); - image.setTopicId( Integer.parseInt( strTopicId ) ); + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + FileItem fileItem = multipartRequest.getFile( Constants.PARAMETER_IMAGE_FILE ); + Image image = new Image( ); + boolean bError = false; - if ( ( fileItem != null ) && ( fileItem.getName( ) != null ) && !"".equals( fileItem.getName( ) ) ) + if ( ( fileItem == null ) || ( fileItem.getName( ) == null ) || "".equals( fileItem.getName( ) ) ) { - image.setValue( fileItem.get( ) ); - image.setMimeType( fileItem.getContentType( ) ); + bError = true; + addError( MESSAGE_FILE_MANDATORY, request.getLocale( ) ); } - else + + if ( ( strName == null ) || strName.trim( ).equals( "" ) ) { - image.setValue( null ); + bError = true; + addError( MESSAGE_NAME_MANDATORY, request.getLocale( ) ); } - image.setWidth( 500 ); - image.setHeight( 500 ); + if ( !bError ) + { + image.setName( strName ); + image.setTopicId( Integer.parseInt( strTopicId ) ); + + if ( ( fileItem != null ) && ( fileItem.getName( ) != null ) && !"".equals( fileItem.getName( ) ) ) + { + image.setValue( fileItem.get( ) ); + image.setMimeType( fileItem.getContentType( ) ); + } + else + { + image.setValue( null ); + } + + image.setWidth( 500 ); + image.setHeight( 500 ); - ImageHome.create( image ); + ImageHome.create( image ); + } } Map mapParameters = new ConcurrentHashMap<>( ); @@ -780,30 +707,6 @@ public XPage doUploadImage( HttpServletRequest request ) throws UserNotSignedExc return redirect( request, VIEW_MODIFY_PAGE, mapParameters ); } - /** - * Manages the removal form of a image whose identifier is in the http request - * - * @param request - * The Http request - * @return the html code to confirm - * @throws SiteMessageException - * A site message - */ - @Action( ACTION_CONFIRM_REMOVE_IMAGE ) - public XPage getConfirmRemoveImage( HttpServletRequest request ) throws SiteMessageException - { - int nId = Integer.parseInt( request.getParameter( Constants.PARAMETER_IMAGE_ID ) ); - UrlItem url = new UrlItem( AppPathService.getPortalUrl( ) ); - url.addParameter( Constants.PARAMETER_PAGE, Constants.PLUGIN_NAME ); - url.addParameter( Constants.PARAMETER_PAGE_NAME, request.getParameter( Constants.PARAMETER_PAGE_NAME ) ); - url.addParameter( Constants.PARAMETER_ACTION, ACTION_REMOVE_IMAGE ); - url.addParameter( Constants.PARAMETER_IMAGE_ID, nId ); - - SiteMessageService.setMessage( request, MESSAGE_CONFIRM_REMOVE_IMAGE, SiteMessage.TYPE_CONFIRMATION, url.getUrl( ) ); - - return null; - } - /** * Handles the removal form of an image * @@ -816,15 +719,16 @@ public XPage getConfirmRemoveImage( HttpServletRequest request ) throws SiteMess @Action( ACTION_REMOVE_IMAGE ) public XPage doRemoveImage( HttpServletRequest request ) throws UserNotSignedException { - checkUser( request ); int nId = Integer.parseInt( request.getParameter( Constants.PARAMETER_IMAGE_ID ) ); - ImageHome.remove( nId ); - addInfo( MESSAGE_IMAGE_REMOVED, getLocale( request ) ); - - Map mapParameters = new ConcurrentHashMap<>( ); - mapParameters.put( Constants.PARAMETER_PAGE_NAME, request.getParameter( Constants.PARAMETER_PAGE_NAME ) + ANCHOR_IMAGES ); + int nTopicId = Integer.parseInt( request.getParameter( Constants.PARAMETER_TOPIC_ID ) ); + Topic topic = TopicHome.findByPrimaryKey( nTopicId ); + if ( RoleService.hasEditRole( request, topic ) ) + { + ImageHome.remove( nId ); + addInfo( MESSAGE_IMAGE_REMOVED, getLocale( request ) ); - return redirect( request, VIEW_MODIFY_PAGE, mapParameters ); + } + return null; } /** @@ -863,7 +767,7 @@ public XPage getConfirmRemoveVersion( HttpServletRequest request ) throws SiteMe @Action( ACTION_REMOVE_VERSION ) public XPage doRemoveVersion( HttpServletRequest request ) throws UserNotSignedException { - checkUser( request ); + WikiAnonymousUser.checkUser( request ); // requires admin role if ( RoleService.hasAdminRole( request ) ) @@ -881,16 +785,15 @@ public XPage doRemoveVersion( HttpServletRequest request ) throws UserNotSignedE /** * Returns the image list as JSON - * + * * @param request * The HTTP request * @return A JSON flow */ @View( VIEW_LIST_IMAGES ) - public XPage getListImages( HttpServletRequest request ) - { + public XPage getListImages( HttpServletRequest request ) throws JsonProcessingException { String strTopicId = request.getParameter( Constants.PARAMETER_TOPIC_ID ); - JSONArray array = new JSONArray( ); + List imageList = new ArrayList<>( ); if ( strTopicId != null ) { @@ -898,45 +801,15 @@ public XPage getListImages( HttpServletRequest request ) List list = ImageHome.findByTopic( nTopicId ); for ( Image image : list ) { - JSONObject jsonImage = new JSONObject( ); - jsonImage.accumulate( "id", image.getId( ) ); - jsonImage.accumulate( "name", image.getName( ) ); - array.add( jsonImage ); - } - } - - return responseJSON( array.toString( ) ); - } - - // /////////////////// Utils //////////////////////////// - /** - * Checks the connected user - * - * @param request - * The HTTP request - * @return The user - * @throws UserNotSignedException - * if user not connected - */ - private LuteceUser checkUser( HttpServletRequest request ) throws UserNotSignedException - { - LuteceUser user; - - if ( SecurityService.isAuthenticationEnable( ) ) - { - user = SecurityService.getInstance( ).getRemoteUser( request ); + HashMap imageMap = new HashMap<>( ); + ObjectMapper mapper = new ObjectMapper( ); + imageMap.put( "id", Integer.toString( image.getId( ) ) ); + imageMap.put( "name", image.getName( ) ); + imageList.add( mapper.writeValueAsString(imageMap) );; - if ( user == null ) - { - throw new UserNotSignedException( ); } } - else - { - user = new WikiAnonymousUser( ); - } - - return user; + return responseJSON(imageList.toString()); } /** @@ -954,7 +827,7 @@ private LuteceUser checkUser( HttpServletRequest request ) throws UserNotSignedE */ private Topic getTopic( HttpServletRequest request, String strPageName, int nMode ) throws SiteMessageException, UserNotSignedException { - Topic topic = TopicHome.findByPrimaryKey( strPageName ); + Topic topic = TopicHome.findByPageName( strPageName ); if ( topic == null ) { @@ -1039,7 +912,7 @@ private List getTopicsForUser( HttpServletRequest request ) /** * Returns a reference list of pages for user - * + * * @param request * The HTTP request * @param bFirstItem @@ -1061,6 +934,21 @@ private ReferenceList getTopicsReferenceListForUser( HttpServletRequest request, return list; } + /* + * @return the list of pages for user with topic name as value + * @param request + */ + private List getTopicNameListForUser( HttpServletRequest request ) + { + List list = new ArrayList<>( ); + + for ( Topic topic : getTopicsForUser( request ) ) + { + list.add( topic.getPageName( ) ); + } + + return list; + } /** * Builds the page title @@ -1125,7 +1013,7 @@ private ReferenceList getPageExtendedPath( Topic topic, HttpServletRequest reque while ( topic != null && !topic.getParentPageName( ).isEmpty( ) && topic.getParentPageName( ) != null && !topic.getParentPageName( ).equals( strWikiRootPageName ) && !isNameInReferenceList( list, URL_VIEW_PAGE + topic.getParentPageName( ) ) ) { - topic = TopicHome.findByPrimaryKey( topic.getParentPageName( ) ); + topic = TopicHome.findByPageName( topic.getParentPageName( ) ); if ( topic != null ) { @@ -1160,7 +1048,7 @@ private ReferenceList getPageExtendedPath( Topic topic, HttpServletRequest reque /** * Checks if name is already in an item of the reference list - * + * * @param list * The reference list * @param name @@ -1182,7 +1070,7 @@ private boolean isNameInReferenceList( ReferenceList list, String name ) /** * Fills all versions with users infos - * + * * @param listVersions * The version */ @@ -1196,7 +1084,7 @@ private void fillUsersData( Collection listVersions ) /** * Fills the version with users infos - * + * * @param version * The version */ @@ -1221,7 +1109,7 @@ private void fillUserData( TopicVersion version ) /** * Gets the current page URL from the request - * + * * @param request * The request * @return The URL @@ -1233,7 +1121,7 @@ private String getPageUrl( HttpServletRequest request ) /** * Returns if the plugin Extend is available - * + * * @return true if extend is installed and activated otherwise false */ private boolean isExtend( ) @@ -1244,7 +1132,7 @@ private boolean isExtend( ) /** * Stores the current selected language in the user's session - * + * * @param request * The request * @param strLanguage @@ -1261,7 +1149,7 @@ private void setLanguage( HttpServletRequest request, String strLanguage ) /** * Retrieves the current selected language from the user's session - * + * * @param request * The request * @return The Language @@ -1276,13 +1164,19 @@ private String getLanguage( HttpServletRequest request ) strLanguage = request.getParameter( PARAMETER_LANGUAGE ); setLanguage( request, strLanguage ); } + else + { + // otherwise, consider the language stored in the user's session + strLanguage = LocaleService.getUserSelectedLocale( request ).getLanguage( ); + setLanguage( request, strLanguage ); + } return LocaleService.getContextUserLocale( request ).getLanguage( ); } /** * Returns a topic title - * + * * @param topic * The topic * @param strLanguage @@ -1292,7 +1186,7 @@ private String getLanguage( HttpServletRequest request ) private String getTopicTitle( Topic topic, String strLanguage ) { TopicVersion version = TopicVersionHome.findLastVersion( topic.getIdTopic( ) ); - if ( version != null && StringUtils.isNotEmpty( version.getWikiContent( strLanguage ).getPageTitle( ) ) ) + if ( version != null && version.getWikiContent( strLanguage ) != null && StringUtils.isNotEmpty( version.getWikiContent(strLanguage).getPageTitle( ) ) ) { return version.getWikiContent( strLanguage ).getPageTitle( ); } @@ -1301,10 +1195,9 @@ private String getTopicTitle( Topic topic, String strLanguage ) return topic.getPageName( ); } } - /** * Returns a topic title - * + * * @param request * The HTTP request * @param topic @@ -1315,4 +1208,25 @@ private String getTopicTitle( HttpServletRequest request, Topic topic ) { return getTopicTitle( topic, getLanguage( request ) ); } + + /** + * Retrieves the current selected version from the parameter + * + * @param request + * The request + * @return The Language + */ + private Integer getVersionTopicVersionId( HttpServletRequest request ) + { + Integer versionId = null; + + if ( request.getParameter( Constants.PARAMETER_TOPIC_VERSION_ID ) != null ) + { + versionId = Integer.parseInt( request.getParameter( Constants.PARAMETER_TOPIC_VERSION_ID ) ); + return versionId; + } + + return versionId; + } + } diff --git a/src/java/fr/paris/lutece/plugins/wiki/web/WikiDynamicInputs.java b/src/java/fr/paris/lutece/plugins/wiki/web/WikiDynamicInputs.java new file mode 100644 index 00000000..ff83d7ef --- /dev/null +++ b/src/java/fr/paris/lutece/plugins/wiki/web/WikiDynamicInputs.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2002-2023, City of Paris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright notice + * and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice + * and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * License 1.0 + */ +package fr.paris.lutece.plugins.wiki.web; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.paris.lutece.plugins.wiki.business.*; +import fr.paris.lutece.plugins.wiki.service.ContentDeserializer; +import fr.paris.lutece.plugins.wiki.service.RoleService; +import fr.paris.lutece.plugins.wiki.service.WikiLocaleService; +import fr.paris.lutece.plugins.wiki.service.parser.SpecialChar; +import fr.paris.lutece.plugins.wiki.utils.auth.WikiAnonymousUser; +import fr.paris.lutece.portal.service.security.LuteceUser; +import fr.paris.lutece.portal.service.security.UserNotSignedException; +import fr.paris.lutece.portal.service.util.AppLogService; +import fr.paris.lutece.plugins.wiki.service.parser.LuteceHtmlParser; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.HashMap; + +/** + * Upload application + */ +public class WikiDynamicInputs +{ + + + public static HttpServletResponse modifyPage( HttpServletRequest request, HttpServletResponse response ) throws IOException, UserNotSignedException + { + StringBuilder sb = new StringBuilder( ); + BufferedReader reader = request.getReader( ); + String line; + while ( ( line = reader.readLine( ) ) != null ) + { + sb.append( line ); + } + String requestBody = sb.toString( ); + String wikiPageUrl = ""; + + try + { + ContentDeserializer newContent = ContentDeserializer.deserializeWikiContent( requestBody ); + Topic topic = TopicHome.findByPageName( newContent.getTopicPageName( ) ); + LuteceUser user = WikiAnonymousUser.checkUser( request ); + + if ( RoleService.hasEditRole( request, topic ) ) + { + + Integer nVersionId = newContent.getTopicVersion( ); + + int nTopicId = topic.getIdTopic( ); + String strComment = newContent.getEditComment( ); + String strLocale = newContent.getLanguage( ); + wikiPageUrl = newContent.getWikiPageUrl( ); + String strParentPageName = newContent.getParentPageName( ); + String strViewRole = newContent.getViewRole( ); + String strEditRole = newContent.getEditRole( ); + String strPageTitle = newContent.getTopicTitle( ); + String strContent = newContent.getTopicContent( ); + String htmlContent = newContent.getWikiHtmlContent( ); + TopicVersion topicVersion = new TopicVersion( ); + + if ( nVersionId != 0 ) + { + topicVersion = TopicVersionHome.findByPrimaryKey( nVersionId ); + } + topicVersion.setUserName( user.getName( ) ); + topicVersion.setIdTopic( nTopicId ); + topicVersion.setUserName( user.getName( ) ); + topicVersion.setEditComment( strComment ); + htmlContent = LuteceHtmlParser.parseHtml( htmlContent, wikiPageUrl, strPageTitle ); + + WikiContent content = new WikiContent( ); + if ( nVersionId == 0 ) + { + for ( String locale : WikiLocaleService.getLanguages( ) ) + { + content.setPageTitle( strPageTitle + "_" + locale ); + content.setContentLabellingMarkdownLanguage( strContent ); + content.setHtmlWikiContent( htmlContent ); + topicVersion.addLocalizedWikiContent( locale, content ); + } + } + content.setPageTitle( strPageTitle ); + content.setContentLabellingMarkdownLanguage( strContent ); + content.setHtmlWikiContent( htmlContent ); + topicVersion.addLocalizedWikiContent( strLocale, content ); + + TopicVersionHome.addTopicVersion( topicVersion ); + topic.setViewRole( strViewRole ); + topic.setEditRole( strEditRole ); + topic.setParentPageName( strParentPageName ); + TopicHome.update( topic ); + + } + } + catch( Exception e ) + { + AppLogService.error( "Error saving topic version automatically", e ); + } + ObjectMapper mapper = new ObjectMapper(); + HashMap result = new HashMap( ); + + result.put( "action", "publish" ); + result.put( "url", SpecialChar.renderWiki( wikiPageUrl ) ); + String res = mapper.writeValueAsString( result ); + response.getWriter( ).write( res ); + + return response; + } +} diff --git a/src/sql/plugins/wiki/plugin/create_db_wiki.sql b/src/sql/plugins/wiki/plugin/create_db_wiki.sql index f18f41bf..1578ae3d 100644 --- a/src/sql/plugins/wiki/plugin/create_db_wiki.sql +++ b/src/sql/plugins/wiki/plugin/create_db_wiki.sql @@ -41,6 +41,7 @@ CREATE TABLE wiki_topic_version_content ( locale VARCHAR(50) DEFAULT '' NOT NULL, page_title VARCHAR(100) DEFAULT '' NOT NULL, wiki_content LONG VARCHAR, + html_wiki_content LONG VARCHAR NULL, PRIMARY KEY (id_topic_version , locale ) ); diff --git a/src/sql/plugins/wiki/plugin/init_db_wiki.sql b/src/sql/plugins/wiki/plugin/init_db_wiki.sql index 374a5c5c..e5edd16c 100644 --- a/src/sql/plugins/wiki/plugin/init_db_wiki.sql +++ b/src/sql/plugins/wiki/plugin/init_db_wiki.sql @@ -1,12 +1,4 @@ --- --- Dumping data for table wiki_topic_version --- - -INSERT INTO wiki_topic_version (id_topic_version, edit_comment, id_topic, lutece_user_id, date_edition, id_topic_version_previous) -VALUES (1,'',1,'admin','2014-05-31 14:42:56',7); - - -- -- Dumping data for table wiki_topic -- @@ -21,12 +13,4 @@ VALUES (1, 0, 'home', 'none', 'none', ''); INSERT INTO wiki_image (id_image, name, mime_type, file_value, id_topic, width, height) VALUES (1,'LUTECE logo','image/png',0x89504E470D0A1A0A0000000D49484452000001030000006E0802000000ACAEE1AC00001FE74944415478DAED5D097814C5B6EEEE99C94CF60059212401040261DF6447443615914544F6451645B8A02817BD208B5C54DCD91EA88022283EBDA0080802221802886109102010882109D9F764D6EEF74F1AC721D33D4B4FF74C7CB7FF8F8FAF7ABA525D55A7FE3AE754579F22870E1D4AC890F15F0FF291471EF1761D64C8F03E6426C8906186CC041932CC909920438619321364C8304366820C1966C84C9021C30C9909326498213341860C336426C8906186CC041932CC909920438619321364C830437226F8AB886A234133DE6EA8A7412A941A93514B10FF752D67F1B793BB984C50524487702A21940CF5231B68F03F515F43FA28CCDD51A2630AAA88422D5358CD649432A7B29952DDDFA7931C8152A8031AC4FB06452BD5C12A9F20FCAF540792A482614C465DB951576AD097E1FFEAB23B15455769A3CEDBF515192AC83DA246EEBE6403F33F02FFE347C8BDD82C71024287E86F9530A773E8B2BADA7A1198A056109D23A91E8DA8AE91949FCAA93F6118E24A2173328B3E954DE757FD5D29A150F90536681518D6C6BFDE0324A574AAE1B4A9B238ADBCE0727941AAC950E9ED16B8058DD22CF79E8DA82E9194AF53AD3773E372019D9485A9902EA8AE5B72778B09D080635B2986365560E2178C8BF9F4968BA6F492BAD52FF6A1520787371D1218DE8E24298145307459FEA5BCF41F0DDA626FB7C66504FA10E35A2B06C609973B847D3E97DE92628281E0EDD6DC834026502431A42935BEB5129DE23EA0228E64D0DB2F9BA04CBDDD218E1AAEF069D0B86F8398BE24E59CFAB3DF70DA5874E7D7828C9F6993DEDB2D730A0A8A78B4A9E299568A0031E40E1571E816BDE38AB1B40E984C4298D03E9C9AD15E1113448A5B153858FF7BD5B43BCD64A2BDDD2B3C088EE80855A05407895BAC515F9E9F7EB0E4EEEFDE6E9F03748A30CBBD51A0C872AF3210BBAE9ABE4B3379D7BD769909235B2826B75588DC1956B89047AF3E6544EFD429C00A8A68FE44BD860F4AF70830E1EEB5DD70B2BDDD566E3C1DAF189FE08611EC08C9B9F45BA78C980DBD05179880E13FBBA3727013A196B1D3C82C6396271AF3EA8C274D29D48D12C605D46F21F5832A8B6F665DFEA266EDB50E0116D10B9D9403622597FBAD526665A2D15B9EB4B34CF055128BBA2BA11F3D53AD121DF3C649E3F522EF9301CE71E3B653D401919E799CAE322F33655BDD71A3FD55C4AB3D946DC33C24F7222DB322D1E895E513A798A051126FF653350D91CE26E280DE442C3961482DF426194083B84ECF8BEE18D887515F713B79435D20839F8A78EB2155ACD80EA17D688DC46BC70D69C59E96BB534C78F941659F680FCD0AD628D632F38F18BDB5A04452CAD80E337D831A7BFED1DA8A9CDBC91B19DA9BDE1286FFE21ECAEE0DBD207718480B8E183CBCA0E498094F36574C6B27A1AB641F570B99C5C70D5E594D8A6A393224AAABB71A5E9A7B2E3BF56B6F3D1D1813AF9820A58B6C1F29F9F4D213469307E740074C681746ADE8A3A43CAA1E6BE3403ABDF19CA7D714421A768B6A31C29BCD2688DC1B7B8BEE9CF4CAA33B47524B7B2A4951E4AEF02104BD2DF92ECDF4E945CFADA4D96342B09A5C3F5015A476AD4465ABC15464029BA6EF5E36A61E74BF96EF9E31FE92C9AB17D46AF5BC79F32C979B376F2E2D2DB5CD366CD8B0F8F878367DFAF4E9E3C78FF315A809888AEB3487A41CCF88110D34037B4639DF90ECBCAAA3A7739DCCCC3074C6B9FFA92ECBB49FAD499326A3478F7658DA9E3D7BD2D2D29C796E035F72ED232A77DE9D914191CAF841546C372A3082F0F1238C5ABA2C97BE75D278E5005359E87C39AB4F1993B21CDB03102B84EB30DB575F7D9599C9DB99F69830A3BD62D8032EEB479FFE2F2A5A0E60D3A66B47F43FBF27BC47FF447E1533FBA0C1C0D327010101BB77EFB65C4E983021379763B4BDF6DA6B0F3DF4109BDEB56BD7279F7CC2F7B8987653FD9D5B336D1E1B3877424BE71B929A5EB6F1CBEBCEE7AF2AB995717EB3FD3C5DBB76FDF7BFFFEDB0A865CB962526263AF3D0E73B2A873415EA1E90A4AACB7865E7B1358E466D188EAF375ED9EF7C61772B99E70E1A1CDA48FDFBF77FF5D5571D96B670E1C20B172EF0569C8F09A1BEE4A6212A95EB1D22051380CDE74D3FDCE4D695E232C12F382EB6E32C276B253513803F2E6CA92CB637978BCB84487F72E32095422011489FC1AF2A9AF4E4BBED2A1380F5C9C683B71CA805699930A793C097681231A144C7CC3860D07171415C268006208393B5F20013601DDD4EDE602783B84C58D055D93F46200F941DC7A81E9C6C27830026145433B37EE435075848C884A80072032606410E93444C003EBB64FAF61A07154464028C229846CE57A95E904F9736F5AD7F896D18D0AE65089BAED69A0E27E558DF2D28D69F4B2D72B5E1772E6D2F2FB8C277D79A0946A3F18D37DEE0CC969A9A5A54E4E0D18D83C8758FA88439CA645094E699CD84D5E65CBAF016FDC759D39DF34C590E552F46D1F26153E639D3D543AE96FCF105D3DE1BF65C676B26545454BCF3CE3B9CD92E5DBAC4E940DEAB3F2713042B04424A2694EB8949FBF4B62BAA2232C12585C089DE9DC2C60C8D65D345A5FA65EB2EBADFF0EAF23BB77F5FCF77D79A090683E1D1471F15FC20B71442E767545D27582E4D374FE87F7A4B944FF68AB5CC94FD0686BF246B261417178F193346C05338988019E1F3C755C16A814B68D231015872C27821AF3615C4628242E5DFA2E76B847B6B87523001484B5A6DD49571DE128B093001B63FEE2378C9080A810C6EC4A6E99CCBBA1F5E234CA2BD195C74CCDE6E03A998D0A23EF94E7FE19BEF256502E71AB3584C088EECD430FE29376B28111372AEEF2EC93EC3794B2C26248492ABFB09943B15D65C3DEA03CBA576FB64A6B2409486B3F8E69AE9F34BBC0692544C18DF5AF1742BE12F1725654276857939B5D68F6231A151C2B8A0B0B66ED65022265414A666A67CCE794B2C264C69AB18D942A0DC553D672ADB0D67D374C14DDD37F38495C3878C5266EE615E0D2315133E18E0D6663B4999003C77D09055719FA214850924A968D16B09A574F13DA20D2462026D325C4F5CC1D01CEFDAC562C2FA41AAC642BFC2D14CDC4EFADF5B393026EF329CF95C583976F0EC0103DF467D4998505F436E7BCCADEF12A56602AC23D848D6BF88C204BF90A6B11D66B85F3D899800645EDC565174CDF677519810E14F7E3C44A8DC951ADF67BFB55CE9F62CA4EFA68AD56A0B369E331E48E75E4C9584096DC3A8557D9D0B54C003A99970F016BD3EF9BEA9511426D46BD83DB2C570F7AB271D13726FEC2BBAF3ABEDEFA230A14B24B5B49740B99381119AF15BFEBC62AA370F870A13ABD516ECBD61FAF80277B19230E1A118EAC5AE759A09BFE5D02B4F8ACF84B0260343631F76BF7AD231A130F344DE4D8ED752A23061601C35B7B340B95311F1EA11EFB269465FA9DD2264203A446296F9F34ECE5B923061440BC5D4B66EEDC5959A09378A99178FDEE73C89C284A896A342A2BAB85F3DE998509A7B3E3B7597EDEFA230C19DCF941571DD7D862C61D34C79AE76C734B19A6C8DD44266D1316EA75912264C6BA778B2799D6642919699B24F7C26346E3B25A0810BFB26F8201D132A8B6FFE7181E36D60ADDD16180AB6790E1D3A6467C72130BB83F2D16642DFA9B51AA2EA37974D4BB170C4E26E2533F347C74C6018A6A4A4C436CF9E3D7B76EEDC69A7FCDA4C58D84DD9B7B15B9F2949CD0413438CDCADB77EE3280A139A7499AB0968E87EF5A46382AE2A2FFDCCFBB6BF3BB3EFE8871F7EF8F0C30FED6458DC43D943E8E769CACE63555D27B269FACE79F33B3509A03711A3F7707FE7E0CCBE23FBBB8F095B262CEFADECE8DE67FB52330118B7575F61D527A230E181EE8B549A10F7EB261D138CFA8AB493AB6C7F178509ABFBA91242052EA1AA7ACF56B6B9F77940CD268B37C56A722D80097A2E9F591226BCDC4DD9A76EEB04BA4627D0E2EB84799A0017BEB9E183744CD057E5DF3CC3D199A230E155373E5956F5795E99F0189B36DD3C5EB3DD487C785A274C6FA7185EB7FD84622D33590A3FA1DD9480FA75DA4FA82A49CF38FFB1EDEFA278CCCF75540E15FA758EF9D39C2EE3D8349D99ACDBB744AC265B23B79299E1849F209AC73CB285624ADD5E3B4A2F61E61F9160ED287E74486467F7AB271D13CAF22E645DF9CAF677519830B695625C6B81728742805A60D3747E9AEEDBF96235D91A570B99573CB976D43F865A50B7DF279CBD4BAF4894E27DC2A0D0D8FEEE574F3A261465FE9A7B739FEDEFA2306170136A4E2781725734EDED3368319B66CA72B43B9F15ABC9D648CA328709E5BC250913DA87532BFBD46926FC749B5EFBBB04EF981BF5886CFE84FBD5938E097937F717669EB0FD5D1426748DA296F414FA662DAA8D7AF83DDF80D15568B73E2D5693ADB1EFA669D3790FBE630EF7233F195AA7F71DD97EB9260A135CFD5A8D0FD23181EFCB355198D028D0FCF9B2B08A9121D19AB19BEE5D304CF5A72309A3F841F0ED7CB926D55ED4F503558DDD0800283513E61E36D43A7E429CBDA894B245AFA594C2DD5311246202439BAE27AEE03C6641ACBDA89B87A822FD85C89D54076AA6FEE5C0E8F72D35658A1F017FF64143768507F7A212EEED53272466427E1533FD406DB749A3D1ECDDBBD772E90C1376ECD8B16DDBB65A19A2DB4C0A0C6DE5660D2562426551DA1F17B770DE128B09C282FAD480D44CF992D404B217C694EF0D899B0495C38BAC0A73B817BEBB5231C19D6F97088999C0170F6FCF9E3DFEFEFE6CFA85175EB8768D63F7F29A356B3A74E8C0A63FFAE8236BF2B01025EE9D444CB0130F4F2C26748CA096F716E82AA8FACE51B6BEF75CA6345BFBA508FBDBAD613F1E9E544CA048E20B37BE679594092B128D67EF726C52DFB46953D3A64DD9F4CA952B39E3DB7DFEF9E75151F7DE9D2D59B2E4D4A953B53228D541CD7B2C76B3861231E1C6E935866AEEC81462314149113B87F9680471818A4A500F7FDB72A9DBBB98CE12CD4102FE75DC78319F37D28B544C005EECAA7C48688C03E998506D2426FEC0FDBE7DC58A153D7AF460D367CE9C8121542B434242C2071FFCF5A1EDAC59B3D2D3D36DCB69D2798E2630DA9D4A4AC1045D656EFA6F1FF0DD1531B6C5A2EECA5E8D84C99DD44CD84A0684B1178CB64CF7ED7CA6DCD9B897F651A1272672C534B1404226C406931F0D1018F7463A26ECBA6ADA71995B453EFBECB34F3FFDD7E2DD962D5BE013D3F4BDCE8B89898112888B8B632F8D46E3A851A3AAAAAA6CCB090C6B139D30DE9D4A4AC184ECD45DA5B9E7F9EE8AC88407EA91EF3D2CD03056759FAAECF0577856BAF096E1C47A3AF71A9C7DF3B5C247193F90A92830659C76B5E42F2E9BBEBEEA6CBC23919900BCD44DD94FD006246B2610462D53CD1D9B84CE49D11F75812498189EFD51CF77FE5A6868283C60B5FAAFAF90EFDEBD7BE3C68DF2F2F2E8E8E8F8F87895EA2F01EFDEBD7BC306BEA872648D5A6824A0E12C44678259219CFD90E00FF7536BDF11E76A01F0FEFBEFFFFEBBE3259DC5DD953D04A905B25E63CD53EB88FBCFA566749574CE25521D40D68F23D5FE0262E095EACC9B2CB47663A5D7DA959D9797C7996DD5AA55A9A9BC9F95F232417018BCFB98C00F5366B2DE950D2A7C01F02C98366DDA33CF3CE3B09CEAEAEA499326716E6167E1E68B05D199603F001E2176344877C2E029DB3EA1EA652FA4AC0026380C8047481D1795101A094F0A26146BCD5F69E8EC76889F9FDFF2E5CB2DAB439CD06AB56BD7AE3D74C84140C2D80E33FD429AB8DA7016E232C1615054428258D9F3BB281F167ABEA0AAC77465FB917C775D6582334151090F3021D4975C3750E5E7A2DD280513D6251B0F390A986C6E0C490E1D3A74E6CC999615556B9C3D7B164E339FF1600DDFA098B88EB3AC437C3A0F3199C03019173EAE2AB9653F97E84C88F0379F9F206C11095034EBABEA36910CAEFDD9131C68FD91352E85BD78EF37E3B13F1CCB5D722600DDA2A8D77A2A5D5295645014E91BEC301BA3AB604AEE385320FA023DE27C057C7D7DE12247D7203030302B2BEB4E0D7272729C2FA441E33EE1CD84B89E81FECA0621F7DC15A389B973B74A40212CF26FFD549071D46136D01EED75982D3333B3A2A2C2C947F78AA6163DE8D6F6332A2A810A7B800C8C305BEE653974413A9D9B6AC7DBB185ED06333E040505356AE4D8B5CBC8C8E05C2661E1F89CB5F1098AA7E3BD76DED6ED52E6E59F1DD8451241949078825113F46EBB28117685616A5BC50837B61AB8891BC5E6EFF71DDA4522C23113E03CBDDECB7327315BA3D2402C3862B85BE99DD140297CE23ACD51FB877BFED1FAEA825BBFAFA7BD7A443945122BFB78EE24666B94E98805470DF99E3D9ADEA95368037D88771F16B83D4B304C0CB1EA24F71B658FC1C72F2CAED3F30AA5C6930FA54DBADBC91B7595E2BC967207C16AB3DCC3FD3C2B779A5896C811115D6A38C50420444D2EE9A56C5ECF439D526D24DE3A654CCEF5260D584027346E3B45A5A9E799C71974A59929DB741577BDDDEE7B68E04B2EE9A9F4D8A1F4B0025627D9DB58211D9C6502A056985FB779E0A8EA826A6645A2F176A9D74CE45A50FA0444B799E48123CAB515D999299FF19D93E02D6894C42B0F2ABB444A2EF7BC2A66F9AFC6CC722F1D44EF3C13881A9F018E949BA1C1ECE36609B332D158A4AD2B34B8D7704AD5A8F5D381A109D23DA2A2F06AD6952F694147174B0DF80C33DA2B1E6B26A1DCAF17312B4F1A4B755E93BB6B4C60D1AF3135A5AD027A53DCAAC040DC9F6EDA7ED9A4F5F431E4CE8124EB47F70E8B7D9812DB6D8063509071AC30F3F8BD2D3A75150FC75293DB28EA694496BB913647FFDD71C5A4F7C60AA105429840D4584A235B9857D904BF7FA985D3D9F4D61413DF474975070A957F58DC23210DBB9182DEBBD5064397DCFD3DFFD621A3DED9957EEF02E21ED55231A2B9C24724F570328BDE9662F2D6F2A035043281457D0D39B18DA27F0C45B9314DC01CDA72D194E20D274930E04687377DD4CD38AA954569B937F7EB2AEB8A73EC3C427DC9496D14300DDC39920EE6D0D614E3E502EF7380855B4C6011A4261E8CA27A34A23A84534AA7274A38C44959F4C96C3AA3CE78C6AE42A509090C6D131896E01714EBF439854C75E91F650597CAF32F1BB4C5CEFD491D45B09AECDE9084DCDB8751CE9F649E5EC22465D350059965754BEE2230C1023F15D135924A08A542FDCCAB6F983902FFFCF04D6732AF0815553305D5E633B3D0173975DE10721E4A9F4038D39AA068953A48E913AC52075B4EA9A28D3A83AED4A82F35E8CAB46577CA0B2E1BF5E5DEAEAFC8F0579983C498E5EE6B967B032BB9C3E52BAC660AB54C613571AB8603B975C010E284984CB005ACC910355969602A453B8FF4EF010A86B4CADF64A8AC9B6B415283957B8581A9FAFBC85D5A26C890F1770107136262629A356BE6ED8AC9902132CE9D3B67E70B2D0E268C1D3B76FAF4E9DEAEB60C1922C3E5EF136426C8F87F099909326498E13213E024B46AE56E50441932EA1A9292920A0B0BF9EECA6B47326498213341860C336426C890618640260C1E3C78E0C081818181C9C9C99F7EFAA9D1C8BD91FAC5175F0C0B0BD3E974C5C5C5C78F1F3F77EE1C6736F8E8EDDBB7B75C6ED8B0213333B3569ED6AD5B4F993265FBF6ED292929B87CFCF1C77BF5EAB578B1CB017DE1054D9B36AD71E3C678C48E1D3BAE5CE10EAA959090F0D4534FC5C4C45CBF7E1D0DCCCFCFE7CC3661C284A64D9BAE58B182BD7CE59557D0D28F3FE6381710B5459D699A2E2A2AC2437FFAE927BE4E037AF7EE3D64C8103CFDF4E9D3EBD7AFAF7557A954AE5CB9D27289BABDF79E6B2137D90E47054A4A4ACE9F3F7FF4E8518627EA44505010BAAB4D9B367979797BF6EC3973E60C67B6E6CD9B231B5A575A5A9A9E9EBE7FFF7EDB2812B5AACDE2A38F3EE28C3982CCCB972F47E77FF6D9677CAD60C700B269B5227CF02D8409E000445E5050505656867170E8D0A1356BD670E6DCB2654B78783844151D6D0EBBFBC61B6FFCF2CB2FB6D9D8930D2C217BDF7CF3CD5BB76A07F9419B972D5B0699AD5EBD1A97CF3FFFFC8811235013976AEEE3E3B36BD7AE8080806BD7AE8584841C3B768CF364D2B8B838480883E3F6EDDBF1F1F177EEDC79EEB9E7F47A8E7D13100386D4934F3EC95E7EF1C517B9B9B92FBDF4926DCE912347A210D02F222202D53871E284853FB6DDFBF2CB2F1B0C86B4B434FC8FB46D2BF6EDDB87CE8708708991849E71A91FD80E4727A3A524497EF9E59790946D36DC5AB76E1D4639BA0B1254ABD598DAAE5EBD6A9B938DB9849A040707FBF9F9DDBC7973CE9C3926D37D1F1CA854AAAD5BB72251BF7E7D0C743666236A929191615B20BA7DEDDAB57070415ABE56B06300703E7A8D1D086102E66C4C153366CCA8AEAE7EFDF5D77BF4E8317AF468CEDAA07F21CB59B366810F9B366D82F0264F9ECC2718FBC39A6502D4CB98316330DF086342DFBE7D972C5902A61D3972046246AD380381A1C218B87804248A510EA1724699275C67C2BC79F340F8B7DF7E1B2A0E9D8619B456368AA2302E41C2B973E7620641256D676B96090E8F58B6034B87438EAB56AD6AD1A2053AD37616872A78FFFDF7B76DDB06E5D9B06143CC1A870F1FE6D43F2C133021A26341DD0103068033ACF6B6C5BBEFBE0B9D6C3F8E2FDB5D488C1F3F9E2FCEA997990042635A85A264B5F6D0A143D166F426E657DBCC162620FDCF7FFE131D8441535959C927183BCF659940D41C08022D248C0918A3B03A1CF61DAA0DCB61E6CC994863044041F30D3B014C484D4DC57400B30AE5DBAABECE9D3B83A8F68FD116910948839010105BB15AD9A64F9F8E2979EAD4A9D08AB884D507E658C724B7C0C20488868D48C7778A05E11C13FEF5AF7F6186454BF98616E17526B46CD9121A1332802470D9AD5B37D4157DF4F5D75FDB66B66602BAA95DBB76B0EDF08B1DC1F081650244029300B38E3026B0C31192F8F1C71FED6443D3929292D02EA46112E092F34C06422813E0DEA039F82B5B5701E303CA164A038E045FF5C46502A40332CC9E3D1B0AB05636D413D93077B07A0914055131F7D956DB9A092039A80EA72E2B2B8BF3E9CE3061E7CE9D30C330BAE072F00536F73213D8498B353070093F01660F9FA1891FD189700FF05798603008A040F804C3CA15C6E58103076CF3B04CC0F43C69D224F4358427800970DF376EDCE8EBEB8B2987CF7D87097BA006163360F7EEDDB065E7CFE73870DB552660AC04060642E3A32B38A90545014F1DF6189C45BE56B04C80ED01AF0997502C972F5F76A91FD80EC764DFB66D5B8C5AD860E855589EB5B2612E8015877E662F172E5C3878F0604EA38E6502A4C35AF66C817C4F77C80488094CD8BC7973EFDEBD612EC250E4CCE66526F4E9D367E9D2A516DD57AF5E3D6883EFBEFB0E8AC23633988036B369388BF84356CF720A864DF39D85C13201C311263B1E87E70A600251A3D3DE79E71D880A1AFCE2458EF0BD3000BEFDF6DBEFBFFF1E1E9BA515E027A66ADBCCAE3201B3A942A1808C615E72AE1D41DD0D1A3468F8F0E1762278B24CB05CDA3D0E821BD61D5E5252B27AF5EAE4E464DB6C70122223232DB1F8596309CCC9CECEAE959365025A847904F501256C6D600B1C32A15FBF7E98AAD08D486030A03738972BBCCC04D61CB29CD8872661A0800C9C4B87B8A5D168E072E5E4E46016E45B37640583999EBDE4F4625926C0BAC03C010BF2ECD9B3C2980074ECD8116A0A9D8BD26C976B5973E8975F7E411EF61758ED705E5F78E105DBA25C65026C1ED41924FCEDB7DF38EBF68F7FFC030624DFF1A12C58264021B07A189C292F77ED3B38B6C3A1F4E08C422E7CAC83E68741FBD8638FB1D6115B3790C176CF02CB04B675D0BAFFF9CF7FEC3CDD211330C49FAC01A65D28A2050B165CBA7489339B3799C01E586631873A74E8008D8F347EB1CD6CED2738148C337E02C6AE56ABC59C0A7B003511C6044B697CEBBF308D609C40F048630AC725A64C78FCB6395D6502A67CE834D833103067C560544C9C38111DC2B7724F88ED27D801AADAB76F5F586BECB67EF6303B90C1D68EB2F8091897C1C1C168859DB7250E9900FBC2CFCF6FDAB469ACEDCDE7857A9909D1D1D15BB76E85938009039703060CC010B138D0B52005133087594EDA14CC0400AD808D04C7CEF6169400CCA171E3C6117FDAAC3FFFFC33E71905AFBFFE7AA74E9DA0BED9CB1D3B76C072B07D03405879CCDDBB7747C97C47E5B26B7168E037DF7CC357738F3101B51D366C18065C5A5A1A51B37A1E1B1B0B15619BD3C204F41BC6C35B6FBD75F8F061BE62ED33013A19A6231250741050484848626222E70B132F330195C3C8C0B3E1DB4169B247FD81BEB66606211913D8853FC27526A097D9F90CE62CA61968794EEB9F5D33817D5C5454C4CA988FEAEC58614DE7FAF5EB7FF5D557C78E1DE3E48C8509501A204C525212E79BB5060D1A40BB9E3F7F7ED1A2457CEF7D3DC604F6F50BBC85FDFBF7A3EB50B1AB57AF729ED96161026CB6EDDBB75B860767B1F69900271E661B5422BBC48C7AAA542ACEA55BEFBF599B3D7BF6A851A34E9D3A05F71786414646067EE1CCE91213E069B19770586DAD646B2660CC412A1445B9CA0438A39874615975E9D2A559B366A034FBD6B31660036098A6A7A7A38DECEB27A87BB0C23627BB767EFBF66DE48407054DC579E63971FF2A2A94068A9D3A752AE73AE3CA952BA137608FA5A4A48018B6C39D6502060A0843D49C36C9699A3AEC7087BD07130525D3348DC7B56CD992B58439CFE6B25E45C5A8C5FC68C7C0B3CF04F6CF2DEF37D8455E4EC78965026604765D1E2C6517D384410813C051B8F69016C6220601D27CEE9D4B4CB05C72BEE5B16602F1E7DAB6AB4CC07CB374E952285CA461E061B6B3357959A0EBE11A62222C2D2D7DFBEDB7F9840A0D397FFE7C76B10B5320CA8498394D646B263469D204AE0E8697F511D11660FCC1E8825B8FC22F5CB860EB51D45A3B8236864E76A91F9C6402DB63902FA61EBD5EFFFDF7DFC36CE3CC66CD848080004C31376EDCE05C31271C31017310E6A9279E7882ED4656EE281C066AAD9C2C132C977676FD3803E17B5121308D46C339535A002384A839FFD87E51C80652592E411E5BC58A6101065A6E296AC0B9B8661FF8AB8888088C6F3BCB7C965A614A76E65C36740572E6E7E7DBD90A8606A2404BFDD11624ECF48CBFBF3F5CCF9C9C1C4E1B0364B0A431673BEC61CE0E77BEF7C2C3C3A1796C5F895AC04A07D560CFC046F9F8852FBF4B776B956C0D760CB8D30FF73541DE952D4306213341860C16321364C8304366820C1966C84C9021C30C9909326498213341860C336426C8906186CC041932CC909920438619321364C8304366820C1966C84C9021C30C9909326498F17FFBAC3F4325E2F5CE0000000049454E44AE426082,1,500,500); --- --- Dumping data for table wiki_topic_version_content --- --- --- Dumping data for table `wiki_topic_version_content` --- -INSERT INTO wiki_topic_version_content (id_topic_version, locale, page_title, wiki_content) VALUES (1,'en','wiki : Home','{{{ jumbotron | Welcome to the Wiki | powered by Lutece | This Wiki aims to be a very simple collaborative tool fully integrated to your Lutece site }}}\r\n\r\n= Key features =\r\n\r\n* Use standard Wikicreole syntax\r\n* Provide a very simple and efficient Wiki editor with removable Help panel\r\n* Can be easily customized by macros to add new rendering features (such as Bootstrap Jumbotron !)\r\n* Fully integrated to Lutece platform :\r\n** Use MyLutece authentication and roles\r\n** Compatible with Extend plugin and all its modules (comment, rating, hits, opengraph...) \r\n** Support Lutece\'s avatar and pseudo features\r\n** Use the graphical theme of the site. It will change the same way as all the site when the theme is modified.\r\n** Code rendering skins can be managed into [quot;Site\'s properties[quot; \r\n\r\n== Quick start ==\r\n\r\nTo create a new page, enter a link into an existing page (the page name in lower case with only underscores as extra characters) such as the link below :\r\n\r\n[[my_new_page]]. \r\n\r\nThen click on the link that appears in red (to be created) and edit your new page. You\'re done !\r\n\r\nYou will have also to create some roles for managing editing and deleting permissions and affect them to your users depending on which MyLutece module you are using.\r\n \r\n== Quick rendering samples ==\r\n\r\n//Just click on Edit button to see the code of all this samples. All the syntax is available clicking on the Help button located at the top right corner.//\r\n\r\nThis text use **bold** and //italics//.\r\n\r\nVarious labels can be created, ex : {{{ label | info | Note }}} {{{ label | warning | Caution }}} {{{ label | success | Awesome }}} ... and badges : {{{ badge | 256 }}}\r\n\r\nA sample table (using all bootstrap features) :\r\n\r\n|=URL|=Description|\r\n|[[http://fr.lutece.paris.fr|http://fr.luteceparis.fr]]|Lutece Official Site|\r\n|[[http://dev.lutece.paris.fr/site-demo|http://dev.luteceparis.fr/site-demo]]|Demo site|\r\n|[[http://dev.lutece.paris.fr/fr|http://dev.luteceparis.fr/fr]]|OSS Site|\r\n\r\nA block of code (using [quot;sunburst[quot; skin) :\r\n\r\n{{{ code | \r\n/* Hello World program */\r\n\r\n[hashmark;include[lt;stdio.h[gt;\r\n\r\nmain()\r\n{\r\n printf([quot;Hello World[quot;);\r\n} \r\n}}}\r\n\r\nSome alert boxes :\r\n\r\n{{{ info | This is an info alert }}}\r\n{{{ warning | This is an warning alert }}}\r\n\r\nA table of content :\r\n\r\n!!!TOC!!!\r\n\r\nA fixed size internal image aligned to the right :\r\n\r\n{{ 1 | LUTECE logo |200||right }}\r\n\r\n Some awesome icons with different size {{{ icon | check-circle }}} {{{ icon | cloud fa-3x }}} {{{ icon | cog fa-5x }}}\r\n\r\n \r\n'); -INSERT INTO wiki_topic_version_content (id_topic_version, locale, page_title, wiki_content) VALUES (1,'fr','wiki : Accueil','{{{ jumbotron | Bienvenue dans le Wiki | powered by Lutece | Cet outil se veut être un outil collaboratif très simple pour votre site Lutece }}}\r\n\r\n= Fonctionnalités principales =\r\n\r\n* Utilisation de la syntaxe standard Wikicreole\r\n* Editeur Wiki très simple avec panneau d\'aide escamotable\r\n* Possibilité de personnaliser des macros pour obtenir des rendus spécifiques (ex: classe Bootstrap Jumbotron !)\r\n* Entièrement intégré à la plate-forme Lutece :\r\n** Authentification MyLutece et gestion des rôles\r\n** Compatible avec le plugin Extend et tous ses modules (comment, rating, hits, opengraph...) \r\n** Support des avatars et des pseudos Lutece\r\n** Compatible avec les thèmes graphiques du site.\r\n** Le rendu des blocs de code est configurable dans [quot;Gestion des propriétés du site[quot; \r\n\r\n== Premiers pas ==\r\n\r\nPour créer une nouvelle page, entrer un lien dans une page existante (le nom technique doit être en minuscules et underscore) comme le lien ci dessous :\r\n\r\n[[my_new_page]]. \r\n\r\nEnsuite cliquer sur ce lien (qui apparait en rouge de manière à indiquer que la page n\'existe pas encore). Vous arrivez alors sur cette nouvelle page vierge. Saisissez son titre et son contenu, puis enregistrer. C\'est fait !\r\n\r\nVous aurez aussi à gérer les rôles de modification/suppression et les affecter aux utilisateurs.\r\n \r\n== Quelques exemples de rendu graphique ==\r\n\r\n// Vous pouvez cliquer sur le bouton Edition pour voir le code source Wiki de tous ces exemples. Toute la syntaxe est disponible via le bouton d\'aide situé en haut à droite.//\r\n\r\nCe texte contient des mots en **gras** et en //italique//.\r\n\r\nDe nombreux types de label peuvent être créés, ex : {{{ label | info | Note }}} {{{ label | warning | Caution }}} {{{ label | success | Awesome }}} ... et aussi des badges : {{{ badge | 256 }}}\r\n\r\nVoici un exemple de tableau (utilisant aussi des styles Bootstrap) :\r\n\r\n|=URL|=Description|\r\n|[[http://fr.lutece.paris.fr|http://fr.luteceparis.fr]]|Lutece Official Site|\r\n|[[http://dev.lutece.paris.fr/site-demo|http://dev.luteceparis.fr/site-demo]]|Demo site|\r\n|[[http://dev.lutece.paris.fr/fr|http://dev.luteceparis.fr/fr]]|OSS Site|\r\n\r\nUn bloc de code (utilisant le thème [quot;sunburst[quot; ) :\r\n\r\n{{{ code | \r\n/* Hello World program */\r\n\r\n[hashmark;include[lt;stdio.h[gt;\r\n\r\nmain()\r\n{\r\n printf([quot;Hello World[quot;);\r\n} \r\n}}}\r\n\r\nDes boîtes d\'alerte :\r\n\r\n{{{ info | This is an info alert }}}\r\n{{{ warning | This is an warning alert }}}\r\n\r\nUne table des matières :\r\n\r\n!!!TOC!!!\r\n\r\nUne image alignée à droite avec une largeur fixée à 200 pixels :\r\n\r\n{{ 1 | LUTECE logo |200||right }}\r\n\r\n Des icônes avec des tailles différentes {{{ icon | check-circle }}} {{{ icon | cloud fa-3x }}} {{{ icon | cog fa-5x }}} \r\n'); diff --git a/src/sql/plugins/wiki/upgrade/update_db_wiki-3.0.1-3.0.2.sql b/src/sql/plugins/wiki/upgrade/update_db_wiki-3.0.1-3.0.2.sql index c4f525fe..cada197d 100644 --- a/src/sql/plugins/wiki/upgrade/update_db_wiki-3.0.1-3.0.2.sql +++ b/src/sql/plugins/wiki/upgrade/update_db_wiki-3.0.1-3.0.2.sql @@ -1 +1,2 @@ -ALTER TABLE wiki_topic ADD COLUMN parent_page_name VARCHAR(100) DEFAULT '' NOT NULL; +ALTER TABLE wiki_topic_version_content ADD html_wiki_content LONG VARCHAR NULL; + diff --git a/webapp/WEB-INF/plugins/wiki.xml b/webapp/WEB-INF/plugins/wiki.xml index 609249ef..a3303047 100644 --- a/webapp/WEB-INF/plugins/wiki.xml +++ b/webapp/WEB-INF/plugins/wiki.xml @@ -30,14 +30,15 @@ xpage wiki/wiki.css - wiki/markitup/style.css - wiki/markitup/wiki/style.css + wiki/toggle_switch.css + wiki/prism/prism.css - + xpage wiki/prettify/run_prettify.js?skin=desert + wiki/prism/prism.js @@ -47,5 +48,5 @@ fr.paris.lutece.plugins.wiki.web.WikiApp - + \ No newline at end of file diff --git a/webapp/WEB-INF/templates/skin/plugins/wiki/custom_input_editor.html b/webapp/WEB-INF/templates/skin/plugins/wiki/custom_input_editor.html new file mode 100644 index 00000000..e5af7dc9 --- /dev/null +++ b/webapp/WEB-INF/templates/skin/plugins/wiki/custom_input_editor.html @@ -0,0 +1,139 @@ + + +

+ + + + + + + + + + + + diff --git a/webapp/WEB-INF/templates/skin/plugins/wiki/diff_topic.html b/webapp/WEB-INF/templates/skin/plugins/wiki/diff_topic.html index 42c920be..c2b458b4 100644 --- a/webapp/WEB-INF/templates/skin/plugins/wiki/diff_topic.html +++ b/webapp/WEB-INF/templates/skin/plugins/wiki/diff_topic.html @@ -4,28 +4,33 @@

#i18n{wiki.menu.diff} [${topic.pageName}]

+ <#if view_diff_html > + #i18n{wiki.menu.diff.source}

#i18n{wiki.menu.diff.html}

- ${diff_html} + ${diff}
+ <#else> + #i18n{wiki.menu.diff.html}

#i18n{wiki.menu.diff.source}

- ${diff_source} + ${diff}
- + + diff --git a/webapp/WEB-INF/templates/skin/plugins/wiki/history_page.html b/webapp/WEB-INF/templates/skin/plugins/wiki/history_page.html index 1da55343..f7473b19 100644 --- a/webapp/WEB-INF/templates/skin/plugins/wiki/history_page.html +++ b/webapp/WEB-INF/templates/skin/plugins/wiki/history_page.html @@ -1,7 +1,7 @@
-
+ @@ -13,55 +13,49 @@ #i18n{wiki.button.backToPage} <#list languages_list as language> - <#if language = current_language > - ${language} - <#else> - - ${language} - - - -
-

#i18n{wiki.menu.history} [${topic.pageName}]

+ <#if language = current_language > + ${language} + <#else> + + ${language} + + + +
+

#i18n{wiki.menu.history} [${topic.pageName}]

- <@messages infos=infos /> + <@messages infos=infos /> -
-

#i18n{wiki.history_page.explanation}

+
+

#i18n{wiki.history_page.explanation}

- - - - - - - - <#if has_edit_role > - - - - <#list listTopicVersion as version > - - - - - - - <#if has_admin_role > - - - - -
#i18n{wiki.history_page.tableHeader.mostRecent}#i18n{wiki.history_page.tableHeader.lessRecent} #i18n{wiki.history_page.tableHeader.date} #i18n{wiki.history_page.tableHeader.author} #i18n{wiki.history_page.tableHeader.comment}#i18n{portal.util.labelActions}
checked > checked >${version.dateEdition} - avatar - ${version.userName!''} ${version.userPseudo!''} - ${version.editComment} - - - -
-
- + + + + + + + + <#if has_edit_role > + + + + <#list listTopicVersion as version > + + + + + + + + +
#i18n{wiki.history_page.tableHeader.mostRecent}#i18n{wiki.history_page.tableHeader.lessRecent} #i18n{wiki.history_page.tableHeader.date} #i18n{wiki.history_page.tableHeader.author} #i18n{wiki.history_page.tableHeader.comment}#i18n{portal.util.labelActions}
checked > checked >${version.dateEdition} + avatar + ${version.userName!''} ${version.userPseudo!''} + ${version.editComment}
+
- \ No newline at end of file + + + diff --git a/webapp/WEB-INF/templates/skin/plugins/wiki/modify_page.html b/webapp/WEB-INF/templates/skin/plugins/wiki/modify_page.html index fcaef7c7..f035f25e 100644 --- a/webapp/WEB-INF/templates/skin/plugins/wiki/modify_page.html +++ b/webapp/WEB-INF/templates/skin/plugins/wiki/modify_page.html @@ -1,387 +1,293 @@ + + + + + + + + + + + + + + +
+ + + + + +
-
- - - - <#if lastVersion??> - + + + + + + <#if version??> + <#else> - + + + + + +
+
+ + #i18n{wiki.button.backToPage} + + + <#if has_admin_role > + + + + + + - - -
-
- - #i18n{wiki.button.backToPage} - - - <#if has_admin_role > - - #i18n{portal.util.labelDelete} - - - -
-
+
+
-
-
- - -

#i18n{wiki.menu.edit} [${topic.pageName}]

- <#assign locales_list = ["fr", "en"]> - - - -
- <#list languages_list as locale> -
- <#if lastVersion?? && lastVersion.getWikiContent( locale )??> -
- - -
-
- - <@select name="parent_page_name" default_value="${topic.parentPageName}" items=reflist_topic sort=true /> -
-
- -
- <#else> -
- - -
-
- - <@select name="parent_page_name" default_value="${topic.parentPageName}" items=reflist_topic sort=true /> -
-
- -
- -
- -
-
- + +