Конфиг

(farm)Config.php

farmconfig.php основной файл, включающий в себя все нижеследующие

<?php if (!defined('PmWiki')) exit();
include_once("$FarmD/local/farmconfig-core.php"); // НАСТРОЙКИ ЯДРА : определяют базовое поведение PmWiki на уровне ее ядра
    // ВРЕМЕННО, только для XAMPP:
    $PubDirUrl = "https://www.pmwiki.ru/pub";
    $FarmPubDirUrl = $PubDirUrl;
include_once("$FarmD/local/farmconfig-markup.php"); // НАСТРОЙКИ РАЗМЕТКИ : определяют обработку разметки и отображение контентной области
include_once("$FarmD/local/farmconfig-patterns.php"); // НАСТРОЙКИ ПАТТЕРНОВ : определяют логику исключений листингов страниц при выборках и поиске, настройки pagelist
if (file_exists("$LocalDir/config-ThisSite.php")) include_once("$LocalDir/config-ThisSite.php"); // ЛОКАЛЬНАЯ КОНФИГУРАЦИЯ
include_once("$FarmD/local/farmconfig-REXT.php"); // REXT-переменные и модификации
include_once("$FarmD/local/farmconfig-editMode.php"); // РЕЖИМ РЕДАКТИРОВАНИЯ

### РЕЦЕПТЫ ###
if (!$rextKeepCore) {
  include_once("$FarmD/cookbook/phFieldProcessing.php");
    $phFieldProcessingArr = array( 	
        'title' => 'text', 
        'description' => 'text',
        // 'CustomHeadCode' => 'textarea', // внимание, с Заглавной Буквы!
        );
    phFieldProcessing($phFieldProcessingArr);         
    phCtimeProcessing();
    $phKeepFields = $phFieldProcessingArr; $phKeepFields['ctime'] = 'text'; // блокируем перезапись полей старницы
    if ($action == "pmform") phFieldsKeeper($phKeepFields); 
}

if (!CondAuth($pagename,'edit')) $EnablePostCaptchaRequired = 1; 
include_once("$FarmD/cookbook/captcha.php"); // https://www.pmwiki.org/wiki/Cookbook/Captcha временно!

include_once("$FarmD/cookbook/phAddObjectModalForm.php");
include_once("$FarmD/cookbook/phAdminPanel.php");
include_once("$FarmD/cookbook/phMultyTags.php");
include_once("$FarmD/cookbook/pagelistmultitargets.php"); // PageListMultiTargets ( http://www.pmwiki.org/wiki/Cookbook/PageListMultiTargets )
  $EnablePLMTLink = 1;
include_once("$FarmD/cookbook/phWikirama.php"); // требует Mini!
  include_once("$FarmD/cookbook/mini.php"); // Mini ( https://www.pmwiki.org/wiki/Cookbook/Mini )
include_once("$FarmD/cookbook/ddmu.php"); // DragDropMultiUpload
include_once("$FarmD/cookbook/phAttachMan.php");
  $phAttachman['EnableDelete'] = true;
  $phAttachman['TableClass'] = 'table sortable';
  $phAttachman['TextareaInsertCommands']['gif'] = 'Mini:%filename%';
  $phAttachman['TextareaInsertCommands']['jpg'] = 'Mini:%filename%';
  $phAttachman['TextareaInsertCommands']['jpeg'] = 'Mini:%filename%';
  $phAttachman['TextareaInsertCommands']['png'] = 'Mini:%filename%';
  $phAttachman['TextareaInsertTemplate'] = "<a href='#' class='ph-dashed'><span>%TextareaInsertCommand%</span></a><br>";

SDV($HandleAuth['pmform'], 'read');
include_once("$FarmD/cookbook/pmform.php"); 
  $PmForm['comments'] = 'saveto={$FullName} form=#commentform fmt=#talkpost';
  $PmFormTemplatesFmt = array_merge(array('ThisSite.CommentsTemplates'),$PmFormTemplatesFmt); // add new templates sources
  $MarkupExpr['inc'] = 'MxInc($args[0])'; // used for comments counting
  function MxInc ($arg) {
    if(!is_numeric($arg)) return $arg;
    return $arg + 1;	
  }	 

if (file_exists("$LocalDir/config-ThisSite-finality.php")) include_once("$LocalDir/config-ThisSite-finality.php"); // ЛОКАЛЬНАЯ КОНФИГУРАЦИЯ: построцессинг

ЯДЕРНЫЕ НАСТРОЙКИ (farmconfig-core.php)

<?php if (!defined('PmWiki')) exit();
### ЯДЕРНЫЕ НАСТРОЙКИ: определяют базовое поведение PmWiki ###
$DefaultGroup = 'Index';
$DefaultPage = 'Index.Index';
$ScriptUrl = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$ScriptUrl = $ScriptUrl.$_SERVER['HTTP_HOST']; 

$WikiDir = new PageStore('wiki.d/{$Group}/{$FullName}'); // см. pmwiki.org/wiki/Cookbook/PerGroupSubDirectories
  // - In international wikis, this code should appear before the call to the XLPage() function. 
  // - использование $FullName обязательно
$EnablePathInfo = 1; // Use "Clean URLs"
include_once("$FarmD/scripts/xlpage-utf-8.php"); // Unicode (UTF-8) allows the display of all languages and all alphabets.
XLPage('ru','PmWikiRu.XLPage');
$EnableLinkPageRelative = 1;  // генерить относительные ссылки вместо абсолютных
$TimeFmt = '%Y-%m-%d, %H:%M'; // представление времени на всем сайте
// $EnableRedirectQuiet = 1; // todo: при случае удалить, непонятно, зачем это
$FarmPubDirUrl = "https://".basename(realpath(dirname(__FILE__) . '/..'))."/pub"; // это автоматическое определение директории фермы (например, "http://master.pmwiki.ru/pub"). В зависимоти от хостинга оно может глючить, в этом случае пропишите путь статично;

if (@$rextMaster) $LockFile = "$FarmD/wikilibThis.d/.flock";
$WikiLibDirs = array(&$WikiDir,
	new PageStore('$FarmD/wikilibThis.d/{$FullName}', @$rextMaster), // служебные страницы REXT редактируются только из мастера
	new PageStore('$FarmD/wikilib.d/{$FullName}'));

НАСТРОЙКИ РАЗМЕТКИ (farmconfig-markup.php)

<?php if (!defined('PmWiki')) exit();
### РАЗМЕТКА и ее Настройки ###
$HTMLPNewline = '<br>'; // теперь перенос строки = <br>
$WikiStyleApply['a'] = 'a'; // возможность назначать классы/стили прицельно для ссылок через %apply=a ...%. Нужно, например, чтобы делать %apply=a class="btn btn-default" data-toggle="collapse"%[[#collapseExample|Показать меню раздела]], т.е. применять классы к ссылкам на якоря. Внимание: классы нельзя будет применять к ссылкам на wiki-страницы (см. pmwiki.org/wiki/PmWiki/WikiStyles-Talk), для этого придется переназначить шаблон генерации ссылок вот так: $LinkPageExistsFmt = "<a href='\$LinkUrl' title='\$LinkAlt'>\$LinkText</a>";
SDVA($WikiStyleAttr,array( // чтобы можно было делать кнопки-действия Bootstrap с помощью PmWiki-разметки
  'data-toggle' => 'a',
  'data-target' => 'a',
  ));

$ToggleNextSelector = 'div.pmtoggle, p.pmtoggle, dl.pmtoggle dt, h4'; // ( см. pmwiki.org/wiki/Cookbook/ToggleNext, pmwiki.ru/Cooks/Toggles )
  

// Настройки -> Таблицы:
$SimpleTableDefaultClassName = "table"; // дефолтный класс таблиц
$EnableSortable = 1; // класс 'sortable' добавляет сортировку по содержимому столбцов (при клике на заголовок)

// Контентная разметка
Markup('lazyweb','<wikilink', "/\\bwww\\.[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]/e", "Keep(MakeLink(\$pagename,'http://$0','$0'),'L')");  // Делать ссылкой любой текст, начинающийся с "www."
Markup('--', 'inline', '/ \-\- /', '&nbsp;— '); // замена двойного дефиса ("--") на тире
Markup('...', 'inline', '/\.\.\./', '…'); // замена трех точек на троеточие

// Дополнительные html-теги
# Общий принцип создания новых тегов: @%html_тег%@ ... @@. Исключение plainText, см. ниже
Markup('@mark@','inline','/@mark@(.*?)@@/','<mark>$1</mark>');
Markup("plainText","block","/@-@(.*?)@@/",'<:block,1>$1'); // разметка @-@вики-код@@ для вывода чего-либо "как оно есть", т.е. без обвязывания в <p>. Используется, например, чтобы в макете дизайна выводить классы из настроек, заданных через PTV на страницах сайта вот так: <!--markup:@-@{ThisSite/SkinConfig$:Container}@@-->

НАСТРОЙКИ ПАТТЕРНОВ (farmconfig-patterns.php)

<?php if (!defined('PmWiki')) exit();
###BASENAME PATTERNs: какие страницы считать "дополнительными"
  # "дополнительные" страницы позволяют обратиться к родителю через {$BaseName} PageVariable  (см. pmwiki.org/wiki/PmWiki/BasicVariables#BaseName)
  # в REXT такие страницы участвуют в генерации Хлебных Крошек;
  # также они могут как-то влиять на поведение страниц, ведь у них есть родитель. Можно это использовать и создавать локальное поведение прямо через wiki-разметку
  # также полезно не забывать о таких страницах в групповых шаблонах (GroupHeader, GroupFooter), например при выводе комментариев
  
$BaseNamePatterns['/-Archive$/'] = '';  // страницы вида *-Archive
$BaseNamePatterns['/-Template$/'] = '';  // страницы вида *-Template
$BaseNamePatterns['/-Sub-.+/'] = '';    // страницы вида *-Sub-*
// почему не добавлено '*-Demo' ? Потому что пока не очевидна необходимость, т.к., вероятно, демо-страниц чаще больше, чем одна
  
  
### PAGELISTS ###
$SearchPatterns['normal']['ph-MainsOfGroups'] = '!^(.*?)\\.\\1$!'; // удаляем страницы вида Name.Name, т.е. Главные групп
$SearchPatterns['normal']['ph-exclude-groups'] = '!ThisSite!'; // удаляем из листингов формата "list=normal" все группы вида ThisSite* .
$SearchPatterns['normal']['self'] = 0; //для list = normal добавляем листинг текущей страницы.
  /* Давайте-ка я поясню, почему сделано так :)
    В pagelist.php оно описано вот так:
      SDVA($SearchPatterns['normal'], array(
      'recent' => '!\.(All)?Recent(Changes|Uploads)$!',
      'group' => '!\.Group(Print)?(Header|Footer|Attributes)$!',
      'self' => str_replace('.', '\\.', "!^$pagename$!")));
    Что это значит? Что при осуществлении pagelist'инга все на тот момент еще не существующие элементы массива будет созданы. 
    В данный момент массива вообще еще нет, поэтому создадим его, соответствующий ключ, и занулим его.
    TODO: возможно, его надо не занулять а... я не знаю что, но зануление вроде тоже работает. */
  
SDV($FPLTemplatePageFmt, array('{$FullName}','ThisSite.PageListTemplates','{$SiteGroup}.PageListTemplates')); // расширяем список страниц, где следует искать шаблоны pagelist  

SDV($MetaRobots, // закрываем от индексации группу ThisSite, в дополнение к уже закрытым
      ($action!='browse' || !PageExists($pagename)
        || preg_match('#^PmWiki[./](?!PmWiki$)|^Site(Admin)?[./]|^ThisSite?[./]#', $pagename))
      ? 'noindex,nofollow' : 'index,follow');

Локальные настройки текущего сайта (config-ThisSite.php)

Этот файл вызывается из farmconfig.php командой
if (file_exists("$LocalDir/config-ThisSite.php")) { include_once("$LocalDir/config-ThisSite.php")};
Таким образом он выполняется только тогда, когда существует в локальной файловой системе.
Этот файл должен существовать в локальной файловой системе всегда (даже на дочерней ферме), т.к. в нем определены доступы к системе.

Локальные настройки нужны для индивидуализации сайта, работающего на REXT. Минимальный набор этих настроек вот такой:

$WikiTitle = 'PmWikiRUS'; // название вашего сайта
$Skin = 'thisSite'; // скин
$DefaultPasswords['edit'] = pmcrypt('secret_pass1');   // пароль на редактирование
$DefaultPasswords['admin'] = pmcrypt('secret_pass2'); // пароль администратора

Дальнейшую индивидуализацию системы рекомендуется производить в этом же файле. К примеру, вот что сделано на pmwiki.ru :

# Локальные настройки pmwiki.ru : 
$EnableHighlight = 1; 
$HTMLHeaderFmt['Highlight'] = '<link rel="stylesheet" href="$FarmPubDirUrl/!phph/!phph-pack-collection/highlightjs/default.min.css" />
<script src="$FarmPubDirUrl/!phph/!phph-pack-collection/highlightjs/highlight.min.js"></script>';
$PmTOC['Enable'] = 1; // автоматическая генерация содержания
$PmTOC['MaxLevel'] = 3;
if (isset($_GET['skin'])) $Skin = $_GET['skin']; // скин можно менять через GET

НАСТРОЙКИ REXT (farmconfig-REXT.php)

<?php if (!defined('PmWiki')) exit();
### REXT-переменные: используются в REXT-функционалах ### 
# Эти переменные не рекомендуется использовать, если нет полной уверенности что задача не решается по-другому.
# Не используйте их вне (farm)config.php
# Старайтесь реализовать задуманное через переменные ядра PmWiki (см. pmwiki.org/wiki/PmWiki/Variables).
###---------------------------------------------------###

# $rextMaster = true; -- эта переменная определена в index.php. Она нужна, как минимум, для определения мастер-копии и открытия /wikilibThis.d/* на запись.
$rextMainSkin = $Skin; // нужно, чтобы в editMode.tmpl (и других шаблонах) знать, какой у нас "был" скин, чтобы подтянуть соответствующий CSS

$makeRedirect = strpos($pagename,"."); // страницы вида /ThisSite.EditForm почему-то тоже обрабатываются движком, сделаем редирект (предлагал внести в ядро: pmwiki.org/wiki/Cookbook/CleanUrls-Talk )
  if ($makeRedirect !== false && $action == "browse") {
    $makeRedirect = str_replace(".","/",$pagename);
    header("HTTP/1.1 301 Moved Permanently"); 
    header("Location: $ScriptUrl/$makeRedirect"); 
    exit(); 
  }
unset($makeRedirect);

  
$rextName = explode("/", $pagename);
  $rextGroup = $rextName[0]; // текущее Имя страницы
  $rextName = $rextName[1];  // ...и Группу. Сделано вручную, т.к. см. pmwiki.org/wiki/PITS/01423
if ($rextGroup == 'Site' || $rextGroup == 'SiteAdmin' || ($rextGroup == 'ThisSite' && $rextName == 'EditForm')) 
  $rextKeepCore = true;  // чтобы при необходимости оставлять "базовый" функционал движка, отключая всё, что может быть не совместимо с ним
  
if ($rextKeepCore) unset($Skin); // удаление $Skin возвращает системный скин

РЕЖИМ РЕДАКТИРОВАНИЯ (farmconfig-editMode.php)

<?php if (!defined('PmWiki')) exit();
### РЕЖИМ РЕДАКТИРОВАНИЯ ###
$UploadPrefixFmt = '/$Group/$Name'; // сортировать uploads по файловой структуре в соответствии с URL
$UploadMaxSize = 20971520; // лимит на загружаеый файл - 20 МБ  
$UploadExts['pdf'] = 'application/pdf';
$UploadExts['csv'] = 'text/csv';
$EnableNotSavedWarning = 1;

$EnableUpload = 1;
// замена пробелов на подчеркивание, конвертация в транслит (см. pmwiki.org/wiki/PmWiki/UploadVariables-Talk )
  $UploadNameChars = "-a-zA-Z0-9_. ";
  $MakeUploadNamePatterns = array(
    '/^.*$/' => 'cyr2ascii', # your custom function
    '/ +/' => '_', # space(s) to underscore
    "/[^$UploadNameChars]/" => '', # same as in scripts/upload.php
    '/(\\.[^.]*)$/' => 'cb_tolower',
    '/^[^[:alnum:]_]+/' => '',
    '/[^[:alnum:]_]+$/' => ''
  );
  function cyr2ascii($m) { # the filename is $m[0]
    $cyr = [
        'а','б','в','г','д','е','ё','ж','з','и','й','к','л','м','н','о','п',
        'р','с','т','у','ф','х','ц','ч','ш','щ','ъ','ы','ь','э','ю','я',
        'А','Б','В','Г','Д','Е','Ё','Ж','З','И','Й','К','Л','М','Н','О','П',
        'Р','С','Т','У','Ф','Х','Ц','Ч','Ш','Щ','Ъ','Ы','Ь','Э','Ю','Я'
    ];
    $lat = [
        'a','b','v','g','d','e','io','zh','z','i','y','k','l','m','n','o','p',
        'r','s','t','u','f','h','ts','ch','sh','sht','a','i','y','e','yu','ya',
        'A','B','V','G','D','E','Io','Zh','Z','I','Y','K','L','M','N','O','P',
        'R','S','T','U','F','H','Ts','Ch','Sh','Sht','A','I','Y','E','Yu','Ya'
    ];
    return str_replace($cyr, $lat, $m[0]);
  }

if (@$_POST['diffclass'] == 'minor') { // не вносить минорные изменения в *RecentChanges
 unset($RecentChangesFmt['$SiteGroup.AllRecentChanges']);
 unset($RecentChangesFmt['$Group.RecentChanges']);}

$EnableGUIButtons = 1; // далее определяем кнопки режима редактирования. Цифры - это "приоритет", они определяют последовательность кнопок.
$GUIButtons ['underline'] = array(115, '{+', '+}', '$[text]', '$GUIButtonDirUrlFmt/underline.gif"$[Underline]"'); 
$GUIButtons ['strikout']  = array(120, '{-', '-}', 'Crossed Out Text', '$GUIButtonDirUrlFmt/strikethrough.gif"Strike Out"');
$GUIButtons ['pagelink']  = array(200, '[[Group.Page|',']]', '$[Page link]', '$GUIButtonDirUrlFmt/pagelink.gif"Link to internal page"'); 
$GUIButtons ['extlink']   = array(210, '[[http:// |',']]', '$[http:// | link text]', '$GUIButtonDirUrlFmt/extlink.gif"Link to external page"');
$GUIButtons ['attach']    = array(220, 'Attach:','', '$[file.ext]', '$GUIButtonDirUrlFmt/attach.gif"Attach File"');
$GUIButtons ['left']      = array(405, '%left%', '', '', '$GUIButtonDirUrlFmt/left.gif"$[Align Left]"');
$GUIButtons ['right']     = array(420, '%right%', '', '', '$GUIButtonDirUrlFmt/right.gif"$[Align Right]"');
$GUIButtons ['textblue']  = array(450, '%blue%', '%%', '$[Blue Text]', '$GUIButtonDirUrlFmt/hightextblue.gif"$[Blue Text]"');
$GUIButtons ['textred']   = array(460, '%red%', '%%', '$[Red Text]','$GUIButtonDirUrlFmt/hightextred.gif"$[Red Text]"');
$GUIButtons ['bgblue']    = array(480, '%bgcolor=blue white%', '%%', '$[Background Blue]', '$GUIButtonDirUrlFmt/highbgblue.gif"$[Blue Text]"');
$GUIButtons ['bgred']     = array(481, '%bgcolor=red white%', '%%', '$[Background Red]', '$GUIButtonDirUrlFmt/highbgred.gif"$[Red Text]"');
$GUIButtons ['bgyellow']  = array(482, '%bgcolor=yellow%', '%%', '$[Background Yellow]', '$GUIButtonDirUrlFmt/highbgyellow.gif"$[Yellow Text]"');
$GUIButtons ['anchor']    = array(500, '[[#', ']]', '$[Anchor Name]', '$GUIButtonDirUrlFmt/anchor.gif"$[Invisible Anchor to Link To]"');
$GUIButtons ['hr']        = array(590, '\\n----\\n', '', '', '$GUIButtonDirUrlFmt/hr.gif"$[Horizontal rule]"');
$GUIButtons ['quotes']      = array(595, '«', '»', '$[Quoted Text]',  '$GUIButtonDirUrlFmt/quotes.gif"russian quotes"');
$GUIButtons ['code']      = array(600, '[@', '@]', '$[UnCoded Text]',  '$GUIButtonDirUrlFmt/code.gif"Preformated Code"');
$GUIButtons ['return']    = array(650, '[[<<]] \\n', '', '','$GUIButtonDirUrlFmt/return.gif"Return"');

if ( $action == 'edit' && !$rextKeepCore ) {
  $_REQUEST['preview'] = 1; // чтобы (:e_preview:) показывалось всегда
  $Skin = 'editMode'; 
  $PageEditForm = 'ThisSite.EditForm'; // кастомная форма редактирования
    
  # phOnClickMarkupper
  $HTMLFooterFmt['scripts']['OnClickMarkupper.js-sitemap']= "<script>phOnClickMarkupper('#sitemap a', 'HREF', '[[%GOAL%|+]]',  'clicked-by-user', 'text');</script>";
  $HTMLFooterFmt['scripts']['OnClickMarkupper.js-attaches']= "<script>phOnClickMarkupper('#attachman .phAttachman_markup a', 'span', '%GOAL%',  'clicked-by-user', 'text');</script> <style>a.clicked-by-user {opacity: 0.5;}</style>";
} 

О последовательности исполнения файлов

В обычном режиме последовательность такая (определена в farmconfig.php):

  1. local/ farmconfig-core.php
  2. local/ farmconfig-markup.php
  3. local/ farmconfig-patterns.php
  4. local/ config-ThisSite.php — этот файл обязан существовать, рекомендуется всю локальную конфигурацию стремиться хранить в нём
  5. local/ farmconfig-REXT.php
  6. local/ farmconfig-editMode.php
  7. подключение Рецептов из cookbook/
  8. local/ config-ThisSite-finality.php — этот файл может существовать, он предназначен для site-wide кастомизаций, требующих наличия подключенных рецептов;
  9. страничные файлы вида local/ Group.Name.php
  10. групповые файлы вида local/ Group.php

В режиме дочернего сайта вики-фермы:

  1. master_local/ farmconfig-core.php — внимание, код забирается с master-фермы
  2. master_local/ farmconfig-markup.php
  3. master_local/ farmconfig-patterns.php
  4. local/ config-ThisSite.php — внимание, код забирается из локальной файловой системы дочернего сайта. Этот файл обязан существовать, рекомендуется всю локальную конфигурацию стремиться хранить в нём.
  5. master_local/ farmconfig-REXT.php
  6. master_local/ farmconfig-editMode.php
  7. подключение Рецептов из master_cookbook/
  8. local/ config-ThisSite-finality.php — этот файл может существовать, но в режиме вики-фермы не рекомендуется его использовать,
  9. local/ config.php — файл будет исполнен, если он существует. Можно использовать для локального подключения Рецептов или перенастройки параметров существующих Рецептов.
  10. страничные файлы вида local/ Group.Name.php
  11. групповые файлы вида local/ Group.php