Sfoglia il codice sorgente

Merge branch 'master' of https://github.com/unaio/una

AntonLV 6 anni fa
parent
commit
0d6ffd07dc
36 ha cambiato i file con 704 aggiunte e 69 eliminazioni
  1. 11 5
      inc/classes/BxDolAcl.php
  2. 12 8
      inc/classes/BxDolCmts.php
  3. 9 2
      inc/classes/BxDolCmtsQuery.php
  4. 12 0
      inc/classes/BxDolModule.php
  5. 7 2
      inc/classes/BxDolPage.php
  6. 128 2
      inc/classes/BxDolWiki.php
  7. 52 8
      inc/classes/BxDolWikiQuery.php
  8. 2 1
      inc/js/classes/BxDolWiki.js
  9. 8 1
      install/sql/system.sql
  10. 0 7
      modules/base/general/classes/BxBaseModGeneralModule.php
  11. 18 0
      modules/boonex/decorous/data/template/system/scripts/BxTemplPagesSearchResult.php
  12. 13 2
      modules/boonex/english/data/langs/system/en.xml
  13. 18 0
      modules/boonex/lucid/data/template/system/scripts/BxTemplPagesSearchResult.php
  14. 18 0
      modules/boonex/ocean/data/template/system/scripts/BxTemplPagesSearchResult.php
  15. 1 1
      modules/boonex/photos/classes/BxPhotosConfig.php
  16. 18 0
      modules/boonex/protean/data/template/system/scripts/BxTemplPagesSearchResult.php
  17. 12 2
      modules/boonex/russian/data/langs/system/ru.xml
  18. 12 1
      modules/boonex/wiki/classes/BxWikiConfig.php
  19. 85 0
      modules/boonex/wiki/classes/BxWikiModule.php
  20. 7 0
      modules/boonex/wiki/install/langs/en.xml
  21. 36 3
      modules/boonex/wiki/install/sql/install.sql
  22. 4 0
      modules/boonex/wiki/install/sql/uninstall.sql
  23. 7 0
      template/css/general.css
  24. 9 6
      template/css/wiki.css
  25. 2 1
      template/scripts/BxBaseAcl.php
  26. 5 6
      template/scripts/BxBasePage.php
  27. 99 0
      template/scripts/BxBasePagesSearchResult.php
  28. 28 0
      template/scripts/BxBaseServices.php
  29. 4 0
      template/search_pages_results.html
  30. 3 0
      template/search_pages_results_live.html
  31. 5 0
      template/wiki_contents.html
  32. 10 0
      template/wiki_controls.html
  33. 6 6
      template/wiki_delete_version.html
  34. 5 5
      template/wiki_history.html
  35. 18 0
      template/wiki_translations_missing.html
  36. 20 0
      template/wiki_translations_outdated.html

+ 11 - 5
inc/classes/BxDolAcl.php

@@ -199,13 +199,19 @@ class BxDolAcl extends BxDolFactory implements iBxDolSingleton
         if(!$iPermissions)
             return false;
 
-        if(false === $iProfileId) {
-            $oProfile = BxDolProfile::getInstance();
-            $iProfileId = $oProfile ? $oProfile->id() : 0;
-        }
+        return ($iPermissions & $this->getMemberLevelBit($iProfileId));
+    }
+
+    /**
+     * Get user's membership level bit for bitwise operarions
+     */
+    public function getMemberLevelBit($iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
 
         $aACL = $this->getMemberMembershipInfo($iProfileId);
-        return ($iPermissions & pow(2, $aACL['id'] - 1));
+        return pow(2, $aACL['id'] - 1);
     }
 
     /**

+ 12 - 8
inc/classes/BxDolCmts.php

@@ -86,7 +86,7 @@ define('BX_CMT_USAGE_DEFAULT', BX_CMT_USAGE_BLOCK);
  * @code
  * $o = new BxTemplCmts('value of ObjectName field', $iYourEntryId);
  * if ($o->isEnabled())
- *     echo $o->getCommentsFirst ();
+ *     echo $o->getCommentsBlock ();
  * @endcode
  *
  * Please note that you never need to use BxDolCmts class directly, use BxTemplCmts instead.
@@ -809,9 +809,11 @@ class BxDolCmts extends BxDolFactory implements iBxDolReplaceable, iBxDolContent
 
     public function isViewAllowed ($isPerformAction = false)
     {
-        $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_view', array($this->getId(), $this->getSystemName()));
-        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
-            return $mixedResult;
+        if (BxDolRequest::serviceExists($this->_aSystem['module'], 'check_allowed_comments_view')) {
+            $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_view', array($this->getId(), $this->getSystemName()));
+            if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+                return $mixedResult;
+        }
 
         return CHECK_ACTION_RESULT_ALLOWED;
     }
@@ -872,9 +874,11 @@ class BxDolCmts extends BxDolFactory implements iBxDolReplaceable, iBxDolContent
 
     public function isPostAllowed ($isPerformAction = false)
     {
-        $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_post', array($this->getId(), $this->getSystemName()));
-        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
-            return false;
+        if (BxDolRequest::serviceExists($this->_aSystem['module'], 'check_allowed_comments_post')) {
+            $mixedResult = BxDolService::call($this->_aSystem['module'], 'check_allowed_comments_post', array($this->getId(), $this->getSystemName()));
+            if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+                return false;
+        }
 
         return $this->checkAction ('comments post', $isPerformAction);
     }
@@ -1553,7 +1557,7 @@ class BxDolCmts extends BxDolFactory implements iBxDolReplaceable, iBxDolContent
     {
         $sModule = $this->_aSystem['module'];
         $oModule = BxDolModule::getInstance($sModule);
-        $CNF = $oModule->_oConfig->CNF;
+        $CNF = isset($oModule->_oConfig->CNF) ? $oModule->_oConfig->CNF : array();
 
         $aContentInfo = BxDolRequest::serviceExists($sModule, 'get_all') ? BxDolService::call($sModule, 'get_all', array(array('type' => 'id', 'id' => $this->getId()))) : array();
         $iContextId = 0;

+ 9 - 2
inc/classes/BxDolCmtsQuery.php

@@ -69,8 +69,13 @@ class BxDolCmtsQuery extends BxDolDb
 
     function getCommentsCountAll ($iId)
     {
-        $sQuery = $this->prepare("SELECT `{$this->_sTriggerFieldComments}` FROM `{$this->_sTriggerTable}` WHERE `{$this->_sTriggerFieldId}` = ?", $iId);
-        return (int)$this->getOne($sQuery);
+        if ($this->_sTriggerFieldComments) {
+            $sQuery = $this->prepare("SELECT `{$this->_sTriggerFieldComments}` FROM `{$this->_sTriggerTable}` WHERE `{$this->_sTriggerFieldId}` = ?", $iId);
+            return (int)$this->getOne($sQuery);
+        }
+        else {
+            return $this->getCommentsCount($iId);
+        }
     }
 
     function getCommentsCount ($iId, $iCmtVParentId = -1, $iAuthorId = 0, $sFilter = '')
@@ -559,6 +564,8 @@ class BxDolCmtsQuery extends BxDolDb
 
     function updateTriggerTable($iId, $iCount)
     {
+        if (!$this->_sTriggerFieldComments)
+            return true;
         $sQuery = $this->prepare("UPDATE `{$this->_sTriggerTable}` SET `{$this->_sTriggerFieldComments}` = ? WHERE `{$this->_sTriggerFieldId}` = ? LIMIT 1", $iCount, $iId);
         return $this->query($sQuery);
     }

+ 12 - 0
inc/classes/BxDolModule.php

@@ -165,6 +165,18 @@ class BxDolModule extends BxDol
     {
         return getLoggedPassword();
     }
+
+    public function serviceIsSafeService($s)
+    {
+        $sService = bx_gen_method_name($s);
+        $aSafeServices = $this->serviceGetSafeServices();
+        return isset($aSafeServices[$sService]);
+    }
+
+    public function serviceGetSafeServices()
+    {
+        return array();
+    }
 }
 
 /** @} */

+ 7 - 2
inc/classes/BxDolPage.php

@@ -270,14 +270,19 @@ class BxDolPage extends BxDolFactory implements iBxDolFactoryObject, iBxDolRepla
         return true;
     }
 
+    public function isVisiblePage ()
+    {
+        return $this->_isVisiblePage($this->_aObject);
+    }
+
     /**
      * Replace provided markers in a string
      * @param $mixed string or array to replace markers in
      * @return string where all occured markers are replaced
      */
-    protected function _replaceMarkers ($mixed)
+    protected function _replaceMarkers ($mixed, $aAdditionalMarkers = array())
     {
-        return bx_replace_markers($mixed, $this->_aMarkers);
+        return bx_replace_markers($mixed, array_merge($this->_aMarkers, $aAdditionalMarkers));
     }
 
     /**

+ 128 - 2
inc/classes/BxDolWiki.php

@@ -152,6 +152,126 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
         return $s . $sControls;
     }
 
+    /**
+     * Generate wiki contents - list of all wiki pages
+     */
+    public function getContents ($sAllExceptSpecified = '', $sOnlySpecified = '')
+    {
+        $aAllExceptSpecified = $sAllExceptSpecified ? explode(',', $sAllExceptSpecified) : array();
+        $aOnlySpecified = $sOnlySpecified ? explode(',', $sOnlySpecified) : array();
+        if (!($a = $this->_oQuery->getPages($aAllExceptSpecified, $aOnlySpecified)))
+            return '';
+
+        $aVars = array('bx_repeat:pages' => array());
+        foreach ($a as $r) {
+            $oPage = BxDolPage::getObjectInstance($r['object']);
+            if (!$oPage->isVisiblePage())
+                continue;
+            $sUrl = $this->getPageUrl($r['uri']);
+            $aVars['bx_repeat:pages'][] = array(
+                'url' => $sUrl,
+                'title' => _t($r['title']),
+            );
+        }
+        usort($aVars['bx_repeat:pages'], function ($r1, $r2) {
+            return strcmp($r1['title'], $r2['title']);
+        });
+        return BxDolTemplate::getInstance()->parseHtmlByName('wiki_contents.html', $aVars);
+    }
+
+    /**
+     * Generate list of wiki blocks with missing translations for the given language
+     */
+    public function getMissingTranslations ($sLang = false)
+    {
+        if (!$sLang)
+            $sLang = bx_lang_name();
+
+        if (!$this->isAllowed('edit') && !$this->isAllowed('translate') || !preg_match("/^[a-z]+$/", $sLang))
+            return _t('_sys_txt_access_denied');
+
+        if (!BxDolLanguages::getInstance()->getLangId($sLang))
+            return _t('_sys_wiki_error_no_such_lang');
+
+        $a = $this->_oQuery->getBlocksWithMissingTranslations($sLang);
+        if (!$a)
+            return _t('_sys_wiki_no_missing_translations', $sLang);
+
+        $aVars = array(
+            'title_title' => _t('_sys_wiki_title_title'),
+            'title_lang' => _t('_sys_wiki_title_lang_missing'),
+            'title_author' => _t('_sys_wiki_title_author', _t('_sys_wiki_orig')),
+            'title_content' => _t('_sys_wiki_title_content', _t('_sys_wiki_orig')),
+            'title_time' => _t('_sys_wiki_title_time', _t('_sys_wiki_orig')),
+            'bx_repeat:blocks' => array()
+        );
+        foreach ($a as $iBlockId) {
+            $aWikiVerMain = $this->_oQuery->getBlockContent ($iBlockId, false);
+            $aPage = $this->_oQuery->getPageByBlockId($iBlockId);
+            $sUrl = $this->getPageUrl($aPage['uri']) . '#bx-page-wiki-container-' . $iBlockId;
+            $oProfile = BxDolProfile::getInstanceMagic($aWikiVerMain['profile_id']);
+
+            $aVars['bx_repeat:blocks'][] = array(
+                'author_url' => $oProfile->getUrl(),
+                'author_name' => $oProfile->getDisplayName(),
+                'url' => $sUrl,
+                'lang' => $sLang,
+                'title' => _t($aPage['title']),
+                'content' => strmaxtextlen($aWikiVerMain['content']),
+                'timejs' => bx_time_js($aWikiVerMain['added']),
+            );
+        }
+        return BxDolTemplate::getInstance()->parseHtmlByName('wiki_translations_missing.html', $aVars);
+    }
+
+    /**
+     * Generate list of wiki blocks with outdated translations for the given language
+     */
+    public function getOutdatedTranslations ($sLang = false)
+    {
+        if (!$sLang)
+            $sLang = bx_lang_name();
+
+        if (!$this->isAllowed('edit') && !$this->isAllowed('translate') || !preg_match("/^[a-z]+$/", $sLang))
+            return _t('_sys_txt_access_denied');
+
+        if (!BxDolLanguages::getInstance()->getLangId($sLang))
+            return _t('_sys_wiki_error_no_such_lang');
+
+        $aVars = array(
+            'title_title' => _t('_sys_wiki_title_title'),
+            'title_lang' => _t('_sys_wiki_title_lang_outated'),
+            'title_author' => _t('_sys_wiki_title_author', _t('_sys_wiki_orig')),
+            'title_content' => _t('_sys_wiki_title_content', _t('_sys_wiki_orig')),
+            'title_time_main' => _t('_sys_wiki_title_time', _t('_sys_wiki_orig')),
+            'title_time' => _t('_sys_wiki_title_time', '"'.$sLang.'"'),
+            'bx_repeat:blocks' => array()
+        );
+        $a = $this->_oQuery->getBlocksWithOutdatedTranslations($sLang);
+        if (!$a)
+            return _t('_sys_wiki_all_translations_up_to_date', $sLang);
+
+        foreach ($a as $iBlockId) {
+            $aWikiVer = $this->_oQuery->getBlockContent ($iBlockId, $sLang, false, false);
+            $aWikiVerMain = $this->_oQuery->getBlockContent ($iBlockId, false);
+            $aPage = $this->_oQuery->getPageByBlockId($iBlockId);
+            $sUrl = $this->getPageUrl($aPage['uri']) . '#bx-page-wiki-container-' . $iBlockId;
+            $oProfile = BxDolProfile::getInstanceMagic($aWikiVerMain['profile_id']);
+
+            $aVars['bx_repeat:blocks'][] = array(
+                'author_url' => $oProfile->getUrl(),
+                'author_name' => $oProfile->getDisplayName(),
+                'url' => $sUrl,
+                'lang' => $sLang,
+                'title' => _t($aPage['title']),
+                'content' => strmaxtextlen($aWikiVerMain['content']),                
+                'timejs_main' => bx_time_js($aWikiVerMain['added']),
+                'timejs' => bx_time_js($aWikiVer['added']),
+            );
+        }
+        return BxDolTemplate::getInstance()->parseHtmlByName('wiki_translations_outdated.html', $aVars);
+    }
+
     /**
      * Check if partucular action is allowed
      * @param $sType action type: add, edit, delete, translate
@@ -367,7 +487,7 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
 
             // insert page
             $sLangKey = '_' . $this->_aObject['module'] . '_' . str_replace('-', '_', $sPageUri) . '_' . time();
-            $sUrl = 'r.php?_q=' . $this->_aObject['uri'] . '/' . $sPageUri;
+            $sUrl = $this->getPageUrl($sPageUri, false, false);
             $iPageId = $this->_oQuery->insertPage ($sPageUri, $sUrl, $sLangKey);
             if (!$iPageId)
                 return array('code' => 10, 'actions' => array('ShowMsg'), 'msg' => _t('_sys_wiki_error_occured', 10));
@@ -563,6 +683,12 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
         }
     }
 
+    protected function getPageUrl ($sPageUri, $bPermalink = true, $bAddRootUrl = true)
+    {
+        $sUrl = ($bAddRootUrl ? BX_DOL_URL_ROOT : '') . 'r.php?_q=' . $this->_aObject['uri'] . '/' . $sPageUri;
+        return $bPermalink ? BxDolPermalinks::getInstance()->permalink($sUrl) : $sUrl;
+    }
+
     protected function isContentChanged ($iBlockId, $sLang, $sContent)
     {
         if (!$sContent) // don't allow revisions with empty content
@@ -627,7 +753,7 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
             }            
         }
         return $aLangs;
-    }
+    }    
 
     public function getVarsForHistory ($iBlockId, $sLang)
     {

+ 52 - 8
inc/classes/BxDolWikiQuery.php

@@ -51,16 +51,20 @@ class BxDolWikiQuery extends BxDolDb
      * @return array with wiki block info
      */
     public function getBlockContent ($iBlockId, $sLang, $iRevision = false, $bAutoMainLang = true)
-    {
+    {        
         $sWhere = '';
-        $aBind = array('block' => $iBlockId, 'language' => $sLang);
-        if (false !== $iRevision) {
-            $sWhere = " AND `revision` = :rev";
-            $aBind['rev'] = $iRevision;
-        }
+        $aRow = false;
+        $aBind = array('block' => $iBlockId);
+        if (false !== $sLang) {            
+            $aBind['language'] = $sLang;
+            if (false !== $iRevision) {
+                $sWhere = " AND `revision` = :rev";
+                $aBind['rev'] = $iRevision;
+            }
 
-        // get latest revision for specific language
-        $aRow = $this->getRow("SELECT `block_id`, `revision`, `profile_id`, `language`, `main_lang`, `content`, `unsafe`, `notes`, `added` FROM `sys_pages_wiki_blocks` WHERE `block_id` = :block AND `language` = :language $sWhere ORDER BY `revision` DESC LIMIT 1", $aBind);
+            // get latest revision for specific language
+            $aRow = $this->getRow("SELECT `block_id`, `revision`, `profile_id`, `language`, `main_lang`, `content`, `unsafe`, `notes`, `added` FROM `sys_pages_wiki_blocks` WHERE `block_id` = :block AND `language` = :language $sWhere ORDER BY `revision` DESC LIMIT 1", $aBind);
+        }
 
         // if translation isn't found for specific language then get latest revision for main language 
         if ($bAutoMainLang && !$aRow) {
@@ -77,6 +81,31 @@ class BxDolWikiQuery extends BxDolDb
         return $this->getAll("SELECT `block_id`, `language`, `revision`, `profile_id`, `notes`, `added` FROM `sys_pages_wiki_blocks` WHERE `block_id` = :block AND `language` = :language ORDER BY `revision` DESC", $aBind);
     }
 
+    public function getBlocksWithMissingTranslations ($sLang)
+    {
+        $aBind = array('lang' => $sLang, 'module' => $this->_aObject['module']);
+        return $this->getColumn("
+            SELECT `wo`.`block_id`
+            FROM `sys_pages_wiki_blocks` AS `wo`
+            INNER JOIN `sys_pages_blocks` AS `b` ON (`wo`.`block_id` = `b`.`id` AND `b`.`module` = :module)
+            LEFT JOIN `sys_pages_wiki_blocks` AS `wt` ON (`wo`.`block_id` = `wt`.`block_id` AND `wt`.`language` = :lang AND `wt`.`main_lang` != 1)            
+            WHERE `wo`.`main_lang` = 1 AND `wo`.`language` != :lang AND `wt`.`block_id` IS NULL
+            GROUP BY `wo`.`block_id`", $aBind);
+    }
+
+    public function getBlocksWithOutdatedTranslations ($sLang)
+    {
+        $aBind = array('lang' => $sLang, 'module' => $this->_aObject['module']);
+        return $this->getColumn("
+            SELECT `wo`.`block_id`
+            FROM `sys_pages_wiki_blocks` AS `wo`
+            INNER JOIN `sys_pages_blocks` AS `b` ON (`wo`.`block_id` = `b`.`id` AND `b`.`module` = :module)
+            INNER JOIN `sys_pages_wiki_blocks` AS `wt` ON (`wo`.`block_id` = `wt`.`block_id` AND `wt`.`language` = :lang AND `wt`.`main_lang` != 1)
+            WHERE `wo`.`main_lang` = 1 AND `wo`.`language` != :lang
+            GROUP BY `wo`.`block_id`
+            HAVING MAX(`wt`.`added`) < MAX(`wo`.`added`)", $aBind);
+    }
+
     public function deleteRevisions ($iBlockId, $sLang, $aRevisions)
     {
         $aBind = array('block' => $iBlockId, 'language' => $sLang);
@@ -92,6 +121,21 @@ class BxDolWikiQuery extends BxDolDb
         return $i;
     }
 
+    public function getPageByBlockId ($iBlockId)
+    {
+        return $this->getRow("SELECT `p`.`title`, `p`.`uri` FROM `sys_objects_page` AS `p` INNER JOIN `sys_pages_blocks` AS `b` ON (`p`.`object` = `b`.`object` AND `b`.`id` = ? AND `p`.`module` = ?) LIMIT 1", array($iBlockId, $this->_aObject['module']));
+    }
+
+    public function getPages ($aAllExceptSpecified = array(), $aOnlySpecified = array())
+    {
+        $sWhere = '';
+        if ($aOnlySpecified)
+            $sWhere = " AND `uri` IN(" . $this->implode_escape($aOnlySpecified) . ")";
+        elseif ($aAllExceptSpecified)
+            $sWhere = " AND `uri` NOT IN(" . $this->implode_escape($aAllExceptSpecified) . ")";
+        return $this->getAll("SELECT `title`, `uri`, `object` FROM `sys_objects_page` WHERE `module` = ?" . $sWhere, array($this->_aObject['module']));
+    }
+
     public function insertPage ($sUri, $sUrl, $sTitleLangKey, $iType = 1, $iLayoutId = 5, $iVisibleForLevels = 2147483647, $sClass = 'BxTemplPageWiki')
     {
         $b = $this->query('INSERT INTO `sys_objects_page` SET

+ 2 - 1
inc/js/classes/BxDolWiki.js

@@ -142,7 +142,8 @@ BxDolWiki.prototype.actionClosePopup = function (oResponce) {
         this.removePopup();
 }
 BxDolWiki.prototype.actionReload = function (oResponce) {
-    loadDynamicBlock(oResponce.block_id, document.location.href);
+    var l = document.location;
+    loadDynamicBlock(oResponce.block_id, l.hash.length ? l.href.replace(l.hash, '') : l.href);
 }
 
 BxDolWiki.prototype.actionDeleteBlock = function (oResponce) {

+ 8 - 1
install/sql/system.sql

@@ -1118,6 +1118,9 @@ CREATE TABLE `sys_objects_search` (
   PRIMARY KEY  (`ID`)
 );
 
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('sys_pages', '_sys_pages', 1, 'BxTemplPagesSearchResult', '');
+
 -- --------------------------------------------------------
 
 --
@@ -4686,11 +4689,15 @@ CREATE TABLE IF NOT EXISTS `sys_pages_blocks` (
   `hidden_on` varchar(255) NOT NULL DEFAULT '',
   `type` enum('raw','html','lang','image','rss','menu','service','wiki') NOT NULL DEFAULT 'raw',
   `content` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `text_updated` int(11) NOT NULL,
   `deletable` tinyint(4) NOT NULL DEFAULT '1',
   `copyable` tinyint(4) NOT NULL DEFAULT '1',
   `active` tinyint(4) NOT NULL DEFAULT '1',
   `order` int(11) NOT NULL,
-  PRIMARY KEY (`id`)
+  PRIMARY KEY (`id`),
+  KEY `object` (`object`),
+  FULLTEXT KEY `text` (`text`)
 );
 
 -- skeleton blocks

+ 0 - 7
modules/base/general/classes/BxBaseModGeneralModule.php

@@ -71,13 +71,6 @@ class BxBaseModGeneralModule extends BxDolModule
     }
 
     // ====== SERVICE METHODS
-
-    public function serviceIsSafeService($s)
-    {
-        $sService = bx_gen_method_name($s);
-        $aSafeServices = $this->serviceGetSafeServices();
-        return isset($aSafeServices[$sService]);
-    }
     
     public function serviceIsBadgesAvaliable()
     {

+ 18 - 0
modules/boonex/decorous/data/template/system/scripts/BxTemplPagesSearchResult.php

@@ -0,0 +1,18 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaTemplate UNA Template Classes
+ * @{
+ */
+
+class BxTemplPagesSearchResult extends BxBasePagesSearchResult
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 13 - 2
modules/boonex/english/data/langs/system/en.xml

@@ -2291,10 +2291,10 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_form_display_wiki_translate"><![CDATA[Wiki Translate]]></string>
 	<string name="_sys_form_wiki_input_caption_block_id"><![CDATA[Block ID]]></string>
 	<string name="_sys_form_wiki_input_caption_lang"><![CDATA[Language]]></string>
-	<string name="_sys_form_wiki_input_caption_lang_info"><![CDATA[★ - main language, red - outdated or missing translation]]></string>
+	<string name="_sys_form_wiki_input_caption_lang_info"><![CDATA[★ - main(original) language, red - outdated or missing translation]]></string>
 	<string name="_sys_form_wiki_input_caption_lang_err"><![CDATA[Please select value]]></string>
 	<string name="_sys_form_wiki_input_caption_content"><![CDATA[Content]]></string>
-	<string name="_sys_form_wiki_input_caption_content_main"><![CDATA[Main Content]]></string>
+	<string name="_sys_form_wiki_input_caption_content_main"><![CDATA[Main(original) Content]]></string>
 	<string name="_sys_form_wiki_input_caption_notes"><![CDATA[Notes]]></string>
 	<string name="_sys_form_wiki_input_caption_submit"><![CDATA[Submit]]></string>
 	<string name="_sys_form_wiki_input_caption_close"><![CDATA[Close]]></string>
@@ -2670,6 +2670,7 @@ If it is not enabled then please consider implement this optimization, since it
     <string name="_sys_not_specified"><![CDATA[Not Specified]]></string>
     <string name="_sys_on"><![CDATA[on]]></string>
     <string name="_sys_off"><![CDATA[off]]></string>
+    <string name="_sys_pages"><![CDATA[Pages]]></string>
 	<string name="_sys_page_block_title_about"><![CDATA[About]]></string>
 	<string name="_sys_page_block_title_account_profile_create"><![CDATA[Create a profile...]]></string>
 	<string name="_sys_page_block_title_account_profile_switcher"><![CDATA[Use site as ...]]></string>
@@ -3117,6 +3118,7 @@ If it is not enabled then please consider implement this optimization, since it
 	<string name="_sys_wiki_error_missing_wiki_object"><![CDATA[Wiki object ({0}) wasn't found]]></string>
     <string name="_sys_wiki_error_action_not_allowed"><![CDATA[Wiki object ({1}) action ({0}) isn't allowed]]></string>
     <string name="_sys_wiki_error_incorrect_page_uri"><![CDATA["{0}" isn't correct page URI]]></string>
+    <string name="_sys_wiki_error_no_such_lang"><![CDATA[No sucn language]]></string>
     <string name="_sys_wiki_error_occured"><![CDATA[Error occured (code:{0})]]></string>
     <string name="_sys_wiki_view_rev"><![CDATA[Version <b>{0}</b> by <a href="{1}">{2}</a>, {3}]]></string>
     <string name="_sys_wiki_lang_mask"><![CDATA[{0} {1} <span class="bx-def-font-grayed bx-def-font-small">{2}</span>]]></string>
@@ -3128,4 +3130,13 @@ If it is not enabled then please consider implement this optimization, since it
     <string name="_sys_wiki_add_block"><![CDATA[Add Block]]></string>
 	<string name="_sys_wiki_add_page"><![CDATA[Add Page]]></string>
 	<string name="_sys_wiki_add_page_text"><![CDATA[Such wiki page doesn't exists.]]></string>
+	<string name="_sys_wiki_no_missing_translations"><![CDATA[No missing translations for {0} language.]]></string>
+	<string name="_sys_wiki_all_translations_up_to_date"><![CDATA[All translations are up to date for {0} language.]]></string>
+    <string name="_sys_wiki_title_title"><![CDATA[Page]]></string>
+    <string name="_sys_wiki_title_lang_missing"><![CDATA[Missing Lang]]></string>
+    <string name="_sys_wiki_title_lang_outated"><![CDATA[Outdated Lang]]></string>
+    <string name="_sys_wiki_title_author"><![CDATA[{0} author]]></string>
+    <string name="_sys_wiki_title_content"><![CDATA[{0} content]]></string>
+    <string name="_sys_wiki_title_time"><![CDATA[{0} updated]]></string>
+    <string name="_sys_wiki_orig"><![CDATA[Orig.]]></string>
 </resources>

+ 18 - 0
modules/boonex/lucid/data/template/system/scripts/BxTemplPagesSearchResult.php

@@ -0,0 +1,18 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaTemplate UNA Template Classes
+ * @{
+ */
+
+class BxTemplPagesSearchResult extends BxBasePagesSearchResult
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 18 - 0
modules/boonex/ocean/data/template/system/scripts/BxTemplPagesSearchResult.php

@@ -0,0 +1,18 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaTemplate UNA Template Classes
+ * @{
+ */
+
+class BxTemplPagesSearchResult extends BxBasePagesSearchResult
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 1 - 1
modules/boonex/photos/classes/BxPhotosConfig.php

@@ -152,7 +152,7 @@ class BxPhotosConfig extends BxBaseModTextConfig
                 'txt_media_exif_aperture' => '_bx_photos_txt_aperture',
                 'txt_media_exif_shutter_speed' => '_bx_photos_txt_shutter_speed',
                 'txt_media_exif_shutter_speed_value' => '_bx_photos_txt_shutter_speed_value',
-                'txt_media_exif_iso' => '_bx_photos_txt_album_iso',
+                'txt_media_exif_iso' => '_bx_photos_txt_iso',
             ),
         );
 

+ 18 - 0
modules/boonex/protean/data/template/system/scripts/BxTemplPagesSearchResult.php

@@ -0,0 +1,18 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaTemplate UNA Template Classes
+ * @{
+ */
+
+class BxTemplPagesSearchResult extends BxBasePagesSearchResult
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 12 - 2
modules/boonex/russian/data/langs/system/ru.xml

@@ -2280,10 +2280,10 @@
     <string name="_sys_form_display_wiki_translate"><![CDATA[Вики: перевод]]></string>
 	<string name="_sys_form_wiki_input_caption_block_id"><![CDATA[Идентификатор блока]]></string>
 	<string name="_sys_form_wiki_input_caption_lang"><![CDATA[Язык]]></string>
-    <string name="_sys_form_wiki_input_caption_lang_info"><![CDATA[★ - основной язык, красным помечен отсутствующий или устаревший перевод]]></string>
+    <string name="_sys_form_wiki_input_caption_lang_info"><![CDATA[★ - основной(оригинальный) язык, красным помечен отсутствующий или устаревший перевод]]></string>
     <string name="_sys_form_wiki_input_caption_lang_err"><![CDATA[Пожалуйста выберите значение]]></string>
 	<string name="_sys_form_wiki_input_caption_content"><![CDATA[Содержимое]]></string>
-    <string name="_sys_form_wiki_input_caption_content_main"><![CDATA[Основное содержимое]]></string>
+    <string name="_sys_form_wiki_input_caption_content_main"><![CDATA[Основное(оригинальное) содержимое]]></string>
 	<string name="_sys_form_wiki_input_caption_notes"><![CDATA[Заметки]]></string>
 	<string name="_sys_form_wiki_input_caption_submit"><![CDATA[Сохранить]]></string>
 	<string name="_sys_format_size_b"><![CDATA[{0} байт]]></string>
@@ -2655,6 +2655,7 @@
     <string name="_sys_not_specified"><![CDATA[Не указано]]></string>
     <string name="_sys_on"><![CDATA[вкл.]]></string>
     <string name="_sys_off"><![CDATA[выкл.]]></string>
+    <string name="_sys_pages"><![CDATA[Страницы]]></string>
 	<string name="_sys_page_block_title_about"><![CDATA[Об...]]></string>
 	<string name="_sys_page_block_title_account_profile_create"><![CDATA[Создать профиль...]]></string>
 	<string name="_sys_page_block_title_account_profile_switcher"><![CDATA[Использовать сайт как ...]]></string>
@@ -3097,6 +3098,7 @@
     <string name="_sys_wiki_error_missing_wiki_object"><![CDATA[Вики объект ({0}) не найден]]></string>
     <string name="_sys_wiki_error_action_not_allowed"><![CDATA[Не разрешенное действие ({0}) для вики объекта ({1})]]></string>
     <string name="_sys_wiki_error_incorrect_page_uri"><![CDATA["{0}" - неправильная ссылка на страницу]]></string>
+    <string name="_sys_wiki_error_no_such_lang"><![CDATA[Нет такого языка]]></string>
     <string name="_sys_wiki_error_occured"><![CDATA[Ошибка (код:{0})]]></string>
     <string name="_sys_wiki_view_rev"><![CDATA[Версия <b>{0}</b> от <a href="{1}">{2}</a>, {3}]]></string>
     <string name="_sys_wiki_lang_mask"><![CDATA[{0} {1} <span class="bx-def-font-grayed bx-def-font-small">{2}</span>]]></string>
@@ -3108,4 +3110,12 @@
     <string name="_sys_wiki_add_block"><![CDATA[Добавить блок]]></string>
 	<string name="_sys_wiki_add_page"><![CDATA[Добавить страницу]]></string>
 	<string name="_sys_wiki_add_page_text"><![CDATA[Такой вики страницы не существует.]]></string>
+	<string name="_sys_wiki_no_missing_translations"><![CDATA[Все переводы на {0} язык присутствуют.]]></string>
+	<string name="_sys_wiki_all_translations_up_to_date"><![CDATA[Все переводы на {0} язык обновлены.]]></string>
+    <string name="_sys_wiki_title_title"><![CDATA[Страница]]></string>
+    <string name="_sys_wiki_title_lang_missing"><![CDATA[Отсут. язык]]></string>
+    <string name="_sys_wiki_title_author"><![CDATA[{0} автор]]></string>
+    <string name="_sys_wiki_title_content"><![CDATA[{0} содержимое]]></string>
+    <string name="_sys_wiki_title_time"><![CDATA[{0} обновлен]]></string>
+    <string name="_sys_wiki_orig"><![CDATA[Ориг.]]></string>
 </resources>

+ 12 - 1
modules/boonex/wiki/classes/BxWikiConfig.php

@@ -9,11 +9,22 @@
  * @{
  */
 
-class BxWikiConfig extends BxDolModuleConfig
+class BxWikiConfig extends BxBaseModGeneralConfig
 {
     function __construct($aModule)
     {
         parent::__construct($aModule);
+
+        $this->CNF = array_merge($this->CNF, array (
+
+            // module icon
+            'ICON' => 'fab wikipedia-w',
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_wiki_txt_sample_single',
+            ),
+        ));
     }
 }
 

+ 85 - 0
modules/boonex/wiki/classes/BxWikiModule.php

@@ -15,6 +15,91 @@ class BxWikiModule extends BxDolModule
     {
         parent::__construct($aModule);
     }
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'Contents' => '',
+            'MissingTranslations' => '',
+            'OutdatedTranslations' => '',
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_wiki Wiki
+     * @subsection bx_wiki-macros Macros
+     * @subsubsection bx_wiki-contents contents
+     * 
+     * @code bx_srv('bx_wiki', 'contents'); @endcode
+     * @code {{~bx_wiki:contents~}} @endcode
+     * 
+     * Wiki contents - list of pages
+     * @param $sAllExceptSpecified optional comma separated list of URIs of pages to filter out
+     * @param $sOnlySpecified optional comma separated list of URIs of pages to show only
+     *
+     * @see BxWikiModule::serviceContents
+     */
+    /** 
+     * @ref bx_wiki-contents "contents"
+     */
+    public function serviceContents ($sAllExceptSpecified = '', $sOnlySpecified = '')
+    {
+        if (!($oWiki = BxDolWiki::getObjectInstance($this->getName())))
+            return '';
+        
+        return $oWiki->getContents($sAllExceptSpecified, $sOnlySpecified);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_wiki Wiki
+     * @subsection bx_wiki-macros Macros
+     * @subsubsection bx_wiki-missing_translations missing_translations
+     * 
+     * @code bx_srv('bx_wiki', 'missing_translations'); @endcode
+     * @code {{~bx_wiki:missing_translations["ru"]~}} @endcode
+     * 
+     * Get list of blocks with missing translations
+     * @param $sLang language to get missing translations for
+     *
+     * @see BxWikiModule::serviceMissingTranslations
+     */
+    /** 
+     * @ref bx_wiki-missing_translations "missing_translations"
+     */
+    public function serviceMissingTranslations ($sLang)
+    {
+        if (!($oWiki = BxDolWiki::getObjectInstance($this->getName())))
+            return '';
+        
+        return $oWiki->getMissingTranslations($sLang);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_wiki Wiki
+     * @subsection bx_wiki-macros Macros
+     * @subsubsection bx_wiki-outdated_translations outdated_translations
+     * 
+     * @code bx_srv('bx_wiki', 'outdated_translations'); @endcode
+     * @code {{~bx_wiki:outdated_translations["ru"]~}} @endcode
+     * 
+     * Get list of blocks with outdated translations
+     * @param $sLang language to get outdated translations for
+     *
+     * @see BxWikiModule::serviceOutdatedTranslations
+     */
+    /** 
+     * @ref bx_wiki-outdated_translations "outdated_translations"
+     */
+    public function serviceOutdatedTranslations ($sLang)
+    {
+        if (!($oWiki = BxDolWiki::getObjectInstance($this->getName())))
+            return '';
+        
+        return $oWiki->getOutdatedTranslations($sLang);
+    }
 }
 
 /** @} */

+ 7 - 0
modules/boonex/wiki/install/langs/en.xml

@@ -2,9 +2,16 @@
 <resources name="en" flag="gb" title="English">
     <string name="_sys_module_wiki"><![CDATA[Wiki]]></string>
     <string name="_bx_wiki"><![CDATA[Wiki]]></string>
+    <string name="_bx_wiki_txt_sample_single"><![CDATA[wiki]]></string>
     <string name="_bx_wiki_object_title"><![CDATA[Wiki]]></string>
     <string name="_bx_wiki_page_home"><![CDATA[Wiki Home]]></string>
     <string name="_bx_wiki_block_home"><![CDATA[Wiki Home]]></string>
+    <string name="_bx_wiki_block_contents"><![CDATA[Contents]]></string>
+    <string name="_bx_wiki_block_administration"><![CDATA[Administration]]></string>
+    <string name="_bx_wiki_page_missing_translations"><![CDATA[Missing Translations]]></string>
+    <string name="_bx_wiki_block_missing_translations"><![CDATA[Missing Translations]]></string>
+    <string name="_bx_wiki_page_outdated_translations"><![CDATA[Outdated Translations]]></string>
+    <string name="_bx_wiki_block_outdated_translations"><![CDATA[Outdated Translations]]></string>
     <string name="_bx_wiki_menu_item_title_system_home"><![CDATA[Wiki]]></string>
     <string name="_bx_wiki_option_design_box"><![CDATA[Default design box for new block]]></string>
 </resources>

+ 36 - 3
modules/boonex/wiki/install/sql/install.sql

@@ -2,14 +2,47 @@
 -- Wiki home page
 
 INSERT INTO `sys_objects_page` (`object`, `uri`, `title_system`, `title`, `module`, `cover`, `cover_image`, `type_id`, `layout_id`, `submenu`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES
-('bx_wiki_home', 'wiki-home', '', '_bx_wiki_page_home', 'bx_wiki', 0, 0, 1, 5, '', 2147483647, 1, 'r.php?_q=wiki/wiki-home', '', '', '', 0, 1, 0, 'BxTemplPageWiki', '');
+('bx_wiki_home', 'wiki-home', '', '_bx_wiki_page_home', 'bx_wiki', 0, 0, 1, 1, '', 2147483647, 1, 'r.php?_q=wiki/wiki-home', '', '', '', 0, 1, 0, 'BxTemplPageWiki', '');
 
 INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `hidden_on`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
-('bx_wiki_home', 1, 'bx_wiki', '', '_bx_wiki_block_home', 0, 2147483647, '0', 'wiki', '', 0, 1, 1, 1);
+('bx_wiki_home', 1, 'bx_wiki', '', '_bx_wiki_block_contents', 0, 2147483647, '0', 'wiki', '', 0, 1, 1, 1);
 SET @iBlockId = LAST_INSERT_ID();
-INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `lang`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
+INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `language`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
+(@iBlockId, 1, 'en', 1, 0, '# Contents\r\n\r\n{{~bx_wiki:contents["wiki-missing-translations,wiki-outdated-translations"]~}}', 'Initial version', UNIX_TIMESTAMP());
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `hidden_on`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_wiki_home', 1, 'bx_wiki', '', '_bx_wiki_block_administration', 0, 192, '0', 'wiki', '', 0, 1, 1, 2);
+SET @iBlockId = LAST_INSERT_ID();
+INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `language`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
+(@iBlockId, 1, 'en', 1, 0, '# Administration\r\n\r\n{{~bx_wiki:contents["","wiki-missing-translations,wiki-outdated-translations"]~}}', 'Initial version', UNIX_TIMESTAMP());
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `hidden_on`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_wiki_home', 2, 'bx_wiki', '', '_bx_wiki_block_home', 0, 2147483647, '0', 'wiki', '', 0, 1, 1, 1);
+SET @iBlockId = LAST_INSERT_ID();
+INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `language`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
 (@iBlockId, 1, 'en', 1, 0, '# Wiki Home\r\n\r\nInsert **your content** here', 'Initial version', UNIX_TIMESTAMP());
 
+-- Wiki missing translations page
+
+INSERT INTO `sys_objects_page` (`object`, `uri`, `title_system`, `title`, `module`, `cover`, `cover_image`, `type_id`, `layout_id`, `submenu`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES
+('bx_wiki_missing_translations', 'wiki-missing-translations', '', '_bx_wiki_page_missing_translations', 'bx_wiki', 0, 0, 1, 5, '', 192, 1, 'r.php?_q=wiki/wiki-missing-translations', '', '', '', 0, 1, 0, 'BxTemplPageWiki', '');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `hidden_on`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_wiki_missing_translations', 1, 'bx_wiki', '', '_bx_wiki_block_missing_translations', 0, 192, '0', 'wiki', '', 0, 1, 1, 1);
+SET @iBlockId = LAST_INSERT_ID();
+INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `language`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
+(@iBlockId, 1, 'en', 1, 0, '### Missing translations for English:\r\n\r\n{{~bx_wiki:missing_translations["en"]~}}', 'Initial version', UNIX_TIMESTAMP());
+
+-- Wiki outdated translations page
+
+INSERT INTO `sys_objects_page` (`object`, `uri`, `title_system`, `title`, `module`, `cover`, `cover_image`, `type_id`, `layout_id`, `submenu`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES
+('bx_wiki_outdated_translations', 'wiki-outdated-translations', '', '_bx_wiki_page_outdated_translations', 'bx_wiki', 0, 0, 1, 5, '', 192, 1, 'r.php?_q=wiki/wiki-outdated-translations', '', '', '', 0, 1, 0, 'BxTemplPageWiki', '');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `hidden_on`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_wiki_outdated_translations', 1, 'bx_wiki', '', '_bx_wiki_block_outdated_translations', 0, 192, '0', 'wiki', '', 0, 1, 1, 1);
+SET @iBlockId = LAST_INSERT_ID();
+INSERT INTO `sys_pages_wiki_blocks` (`block_id`, `revision`, `language`, `main_lang`, `profile_id`, `content`, `notes`, `added`) VALUES
+(@iBlockId, 1, 'en', 1, 0, '### Outdated translations for English:\r\n\r\n{{~bx_wiki:outdated_translations["en"]~}}', 'Initial version', UNIX_TIMESTAMP());
 
 -- Studio page and widget
 

+ 4 - 0
modules/boonex/wiki/install/sql/uninstall.sql

@@ -1,6 +1,10 @@
 
+
+
 -- Delete WIKI content
 
+DELETE FROM `sys_objects_page` WHERE `module` = 'bx_wiki';
+
 DELETE FROM `wb`, `wc`, `wp`
 USING `sys_pages_blocks` AS `wb`, `sys_pages_wiki_blocks` AS `wc`, `sys_objects_page` AS `wp`
 WHERE `wb`.`id` = `wc`.`block_id` AND `wp`.`object` = `wb`.`object` AND `wp`.`module` = 'bx_wiki';

+ 7 - 0
template/css/general.css

@@ -472,3 +472,10 @@ video.bx-player-embed {
     width:100vw;
     height:100vh;
 }
+
+/* --------------- Search */
+
+.bx-sys-search-results-pages {
+    text-align:left;
+    line-height:150%;
+}

+ 9 - 6
template/css/wiki.css

@@ -28,15 +28,13 @@
     max-width:37.5rem;
 }
 .bx-wiki-del-rev,
+.bx-wiki-translations,
 .bx-wiki-history {
     border-collapse:collapse;
 }
-.bx-wiki-del-rev-cell-profile,
-.bx-wiki-del-rev-cell-time,
-.bx-wiki-del-rev-cell-rev,
-.bx-wiki-history-cell-profile,
-.bx-wiki-history-cell-time,
-.bx-wiki-history-cell-rev {
+.bx-wiki-cell-profile,
+.bx-wiki-cell-time,
+.bx-wiki-cell-rev {
     text-align:center;
 }
 .bx-wiki-add-block {
@@ -50,3 +48,8 @@
     float:none;
     display:inline-block;
 }
+.bx-wiki-trans {
+    -webkit-transition: background-color 1500ms linear;
+    -ms-transition: background-color 1500ms linear;
+    transition: background-color 1500ms linear;
+}

+ 2 - 1
template/scripts/BxBaseAcl.php

@@ -29,9 +29,10 @@ class BxBaseAcl extends BxDolAcl
 
 		
 		$aCheck = checkActionModule($iLoggedProfileId, 'show membership private info', 'system', false);
+		$oProfile = BxDolProfile::getInstance($iLoggedProfileId);
 		
         $aTmplVarsPrivateInfo = array();
-        $bTmplVarsPrivateInfo = ((BxDolProfile::getInstance($iProfileId)->getAccountId() == BxDolProfile::getInstance($iLoggedProfileId)->getAccountId() || $aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED) && !empty($aLevel['date_starts']));
+        $bTmplVarsPrivateInfo = ($oProfile && (BxDolProfile::getInstance($iProfileId)->getAccountId() == $oProfile->getAccountId() || $aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED) && !empty($aLevel['date_starts']));
         if($bTmplVarsPrivateInfo)
             $aTmplVarsPrivateInfo = array(
                 'date_start' => bx_time_js($aLevel['date_starts']),

+ 5 - 6
template/scripts/BxBasePage.php

@@ -209,7 +209,7 @@ class BxBasePage extends BxDolPage
      */
     public function getBlockTitle ($aBlock)
     {
-        return $this->_replaceMarkers(_t($aBlock['title']));
+        return $this->_replaceMarkers(_t($aBlock['title']), array('block_id' => $aBlock['id']));
     }
 
     /**
@@ -372,7 +372,7 @@ class BxBasePage extends BxDolPage
     protected function _getBlockRaw ($aBlock)
     {
         $s = '<div class="bx-page-raw-container">' . BxDolTemplate::getInstance()->parseHtmlByContent($aBlock['content'], array()) . '</div>';
-        $s = $this->_replaceMarkers($s);
+        $s = $this->_replaceMarkers($s, array('block_id' => $aBlock['id']));
         $s = bx_process_macros($s);
         return $s;
     }
@@ -384,7 +384,7 @@ class BxBasePage extends BxDolPage
     protected function _getBlockHtml ($aBlock)
     {
         $s = '<div class="bx-page-html-container">' . $aBlock['content'] . '</div>';
-        $s = $this->_replaceMarkers($s);
+        $s = $this->_replaceMarkers($s, array('block_id' => $aBlock['id']));
         $s = bx_process_macros($s);
         return $s;
     }
@@ -401,11 +401,10 @@ class BxBasePage extends BxDolPage
         } 
         else {
             $sContent = $oWiki->getBlockContent($aBlock['id'], false, (int)bx_get($aBlock['id'].'rev') ? (int)bx_get($aBlock['id'].'rev') : false);
-            $sContent = bx_process_macros($sContent);
         }
 
         $s = '<div id="bx-page-wiki-container-' . $aBlock['id'] . '" class="bx-page-wiki-container">' . $sContent . '</div>';
-        $s = $this->_replaceMarkers($s);
+        $s = $this->_replaceMarkers($s, array('block_id' => $aBlock['id']));
         $s = bx_process_macros($s);
         return $s;
     }
@@ -417,7 +416,7 @@ class BxBasePage extends BxDolPage
     protected function _getBlockLang ($aBlock)
     {
         $s = '<div class="bx-page-lang-container">' . _t(trim($aBlock['content'])) . '</div>';
-        $s = $this->_replaceMarkers($s);
+        $s = $this->_replaceMarkers($s, array('block_id' => $aBlock['id']));
         $s = bx_process_macros($s);
         return $s;
     }

+ 99 - 0
template/scripts/BxBasePagesSearchResult.php

@@ -0,0 +1,99 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaBaseView UNA Base Representation Classes
+ * @{
+ */
+
+class BxBasePagesSearchResult extends BxTemplSearchResult
+{
+    function __construct()
+    {
+        parent::__construct();
+
+        $this->aCurrent = array(
+            'name' => 'sys_pages',
+            'module_name' => 'system',
+            'title' => _t('_sys_pages'),
+            'table' => 'sys_pages_blocks',
+            'ownFields' => array('text_updated`, MAX(`text_updated`) AS `updated_max'),
+            'searchFields' => array('text'),
+            'restriction' => array(
+                'visible_for_levels' => array('value' => '', 'field' => 'visible_for_levels', 'operator' => '&'),
+            ),
+            'join' => array(
+                'albums' => array(
+                    'type' => 'INNER',
+                    'table' => 'sys_objects_page',
+                    'mainField' => 'object',
+                    'onField' => 'object',
+                    'joinFields' => array('id', 'title', 'url', 'module'),
+                    'groupTable' => 'sys_objects_page', 
+                    'groupField' => 'object',
+                ),
+            ),            
+            'paginate' => array('perPage' => 10, 'start' => 0),
+            'sorting' => 'last',
+            'ident' => 'id',
+        );
+
+        $this->sBrowseUrl = BX_DOL_SEARCH_KEYWORD_PAGE;
+
+        $this->aCurrent['restriction']['visible_for_levels']['value'] = 1; // for guests
+        if (isAdmin()) {
+            // admin can view anything
+            $this->aCurrent['restriction']['visible_for_levels']['value'] = '';
+        }
+        elseif ($iProfileId = bx_get_logged_profile_id()) {
+            $oAcl = BxDolAcl::getInstance();
+            $iProfileAclBit = $oAcl->getMemberLevelBit($iProfileId);
+            if ($iProfileAclBit) 
+                $this->aCurrent['restriction']['visible_for_levels']['value'] = $iProfileAclBit;
+        }
+        // TODO: check for privacy
+    }
+
+    function displaySearchUnit($aData)
+    {
+        $sModule = $aData['module'];
+        $sIcon = 'file-alt';
+        if ('system' == $sModule || 'custom' == $sModule) {
+            $sModule = '';
+        }
+        elseif (($oModule = BxDolModule::getInstance($aData['module'])) && isset($oModule->_oConfig->CNF)) {
+            $CNF = $oModule->_oConfig->CNF;
+            if (isset($CNF['T']['txt_sample_single']))
+                $sModule = _t($CNF['T']['txt_sample_single']);
+            if (isset($CNF['ICON']))
+                $sIcon = $CNF['ICON'];
+        }
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($aData['url']);
+        $aVars = array(
+            'title' => _t($aData['title']),
+            'content_url' => $sUrl,
+            'updated' => $aData['updated_max'] ? bx_time_js($aData['updated_max']) : '',
+            'ts' => $aData['updated_max'],
+            'module_name' => $sModule,
+            'icon' => $sIcon,
+        );
+        if ($this->_bLiveSearch) {
+            $sTemplate = 'search_pages_results_live.html';
+        }
+        else {
+            $sTemplate = 'search_pages_results.html';
+        }
+        return BxDolTemplate::getInstance()->parseHtmlByName($sTemplate, $aVars);
+    }
+
+    function getAlterOrder()
+    {
+        if($this->aCurrent['sorting'] == 'last')
+            return array('order' => " ORDER BY `text_updated` DESC");
+
+        return array();
+    }
+}
+
+/** @} */

+ 28 - 0
template/scripts/BxBaseServices.php

@@ -29,6 +29,7 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
         return array(
             'GetCreatePostForm' => 'BxBaseServices',
             'KeywordSearch' => 'BxBaseServices',
+            'Cmts' => 'BxBaseServices',
 
             'CreateAccountForm' => 'BxBaseServiceAccount',
             'ForgotPassword' => 'BxBaseServiceAccount',
@@ -317,6 +318,33 @@ class BxBaseServices extends BxDol implements iBxDolProfileService
         return $oSearch->response();
     }
     
+    /**
+     * @page service Service Calls
+     * @section bx_system_general System Services 
+     * @subsection bx_system_general-general General
+     * @subsubsection bx_system_general-cmts cmts
+     * 
+     * @code bx_srv('system', 'cmts', ["sys_blocks", 1], 'TemplServices'); @endcode
+     * 
+     * @code {{~system:cmts:TemplServices["sys_blocks", 1]~}} @endcode
+     * 
+     * Comments block
+     * @param $sObject - comments object name
+     * @param $sId - content id assiciated tith the comments
+     * 
+     * @see BxBaseServices::serviceCmts
+     */
+    /** 
+     * @ref bx_system_general-cmts "cmts"
+     */
+    public function serviceCmts ($sObject, $sId)
+    {
+        $o = BxDolCmts::getObjectInstance($sObject, $sId);
+        if (!$o || !$o->isEnabled())
+            return '';
+        return $o->getCommentsBlock(array(), array('in_designbox' => false, 'show_empty' => true));
+    }
+
     public function _serviceProfileFunc ($sFunc, $iContentId, $aParams = array())
     {
         if (!$iContentId)

+ 4 - 0
template/search_pages_results.html

@@ -0,0 +1,4 @@
+<div class="bx-sys-search-results-pages">
+    <a href="__content_url__">__title__</a>
+    <span class="bx-def-font-small bx-def-font-grayed">__updated__</span>
+</div>

+ 3 - 0
template/search_pages_results_live.html

@@ -0,0 +1,3 @@
+<div class="bx-base-general-unit bx-def-unit bx-def-unit-live-search bx-def-margin-sec-bottom" data-ts="__ts__">
+    <a href="__content_url__"><div class="bx-def-unit-img"><div class="bx-def-unit-img-empty bx-def-thumb-size bx-def-round-corners bx-def-box bx-def-color-bg-box bx-def-box-sizing"><i class="sys-icon __icon__"></i></div></div></a><div class="bx-def-unit-info bx-def-thumb-size-max-height bx-def-padding-sec-left"><a href="__content_url__">__title__</a><br /><span class="bx-def-font-grayed bx-def-font-small">__module_name__</span></div>
+</div>

+ 5 - 0
template/wiki_contents.html

@@ -0,0 +1,5 @@
+<ul class="bx-wiki-contents bx-def-font-large">
+    <bx_repeat:pages>
+        <li><a href="__url__">__title__</a></li>
+    </bx_repeat:pages>
+</ul>

+ 10 - 0
template/wiki_controls.html

@@ -4,4 +4,14 @@
 </div>
 <script>
     window.glBxDolWiki__block_id__ = new BxDolWiki('__obj__', $('#bx-page-wiki-container-__block_id__'), __options__);
+    if (location.hash.length) {
+        var e = $('#' + location.hash.substr(1));
+        e.css('background-color', 'yellow');
+        setTimeout(function () {
+            e.addClass('bx-wiki-trans');
+            setTimeout(function () {
+                e.css('background-color', 'transparent');
+            }, 1500);
+        }, 100);
+    }
 </script>

+ 6 - 6
template/wiki_delete_version.html

@@ -1,12 +1,12 @@
     <table class="bx-wiki-del-rev bx-def-margin-sec-top">
     <bx_repeat:revisions>
         <tr>
-            <td class="bx-wiki-del-rev-cell-checkbox bx-def-border bx-def-padding-thd"><input type="checkbox" name="revision[]" value="__revision__" id="bx-wiki-del-rev-cell-checkbox-__revision__" /></td>
-            <td class="bx-wiki-del-rev-cell-lang bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__language__</label></td>
-            <td class="bx-wiki-del-rev-cell-rev bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__revision__</label></td>
-            <td class="bx-wiki-del-rev-cell-time bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__timejs__</label></td>
-            <td class="bx-wiki-del-rev-cell-profile bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__author_name__</label></td>
-            <td class="bx-wiki-del-rev-cell-notes bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__notes__</label></td>
+            <td class="bx-wiki-cell-checkbox bx-def-border bx-def-padding-thd"><input type="checkbox" name="revision[]" value="__revision__" id="bx-wiki-del-rev-cell-checkbox-__revision__" /></td>
+            <td class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__language__</label></td>
+            <td class="bx-wiki-cell-rev bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__revision__</label></td>
+            <td class="bx-wiki-cell-time bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__timejs__</label></td>
+            <td class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__author_name__</label></td>
+            <td class="bx-wiki-cell-notes bx-def-border bx-def-padding-thd"><label for="bx-wiki-del-rev-cell-checkbox-__revision__">__notes__</label></td>
         </tr>
     </bx_repeat:revisions>
     </table>

+ 5 - 5
template/wiki_history.html

@@ -2,11 +2,11 @@
 <table class="bx-wiki-history bx-def-margin-sec-top">
 <bx_repeat:revisions>
     <tr>
-        <td class="bx-wiki-history-cell-rev bx-def-border bx-def-padding-thd"><a href="__rev_url__">__revision__</a></td>
-        <td class="bx-wiki-history-cell-lang bx-def-border bx-def-padding-thd">__language__</td>
-        <td class="bx-wiki-history-cell-time bx-def-border bx-def-padding-thd">__timejs__</td>
-        <td class="bx-wiki-history-cell-profile bx-def-border bx-def-padding-thd"><a href="__author_url__">__author_name__</a></td>
-        <td class="bx-wiki-history-cell-notes bx-def-border bx-def-padding-thd">__notes__</td>
+        <td class="bx-wiki-cell-rev bx-def-border bx-def-padding-thd"><a href="__rev_url__">__revision__</a></td>
+        <td class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd">__language__</td>
+        <td class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__timejs__</td>
+        <td class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd"><a href="__author_url__">__author_name__</a></td>
+        <td class="bx-wiki-cell-notes bx-def-border bx-def-padding-thd">__notes__</td>
     </tr>
 </bx_repeat:revisions>
 </table>

+ 18 - 0
template/wiki_translations_missing.html

@@ -0,0 +1,18 @@
+<table class="bx-wiki-translations">
+    <tr>
+        <th class="bx-wiki-cell-title bx-def-border bx-def-padding-thd">__title_title__</a></th>
+        <th class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd">__title_author__</th>
+        <th class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd">__title_lang__</th>
+        <th class="bx-wiki-cell-content bx-def-border bx-def-padding-thd">__title_content__</th>
+        <th class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__title_time__</th>
+    </tr>
+<bx_repeat:blocks>
+    <tr>
+        <td class="bx-wiki-cell-title bx-def-border bx-def-padding-thd"><a href="__url__">__title__</a></td>
+        <td class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd"><a href="__author_url__">__author_name__</a></td>
+        <td class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd">__lang__</td>
+        <td class="bx-wiki-cell-content bx-def-border bx-def-padding-thd">__content__</td>
+        <td class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__timejs__</td>
+    </tr>
+</bx_repeat:blocks>
+</table>

+ 20 - 0
template/wiki_translations_outdated.html

@@ -0,0 +1,20 @@
+<table class="bx-wiki-translations">
+    <tr>
+        <th class="bx-wiki-cell-title bx-def-border bx-def-padding-thd">__title_title__</a></th>
+        <th class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd">__title_author__</th>
+        <th class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd">__title_lang__</th>
+        <th class="bx-wiki-cell-content bx-def-border bx-def-padding-thd">__title_content__</th>
+        <th class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__title_time_main__</th>
+        <th class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__title_time__</th>
+    </tr>
+<bx_repeat:blocks>
+    <tr>
+        <td class="bx-wiki-cell-title bx-def-border bx-def-padding-thd"><a href="__url__">__title__</a></td>
+        <td class="bx-wiki-cell-profile bx-def-border bx-def-padding-thd"><a href="__author_url__">__author_name__</a></td>
+        <td class="bx-wiki-cell-lang bx-def-border bx-def-padding-thd">__lang__</td>
+        <td class="bx-wiki-cell-content bx-def-border bx-def-padding-thd">__content__</td>
+        <td class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__timejs_main__</td>
+        <td class="bx-wiki-cell-time bx-def-border bx-def-padding-thd">__timejs__</td>
+    </tr>
+</bx_repeat:blocks>
+</table>