<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
	<channel>
		<title>Cotonti</title>
		<link>https://www.cotonti.com</link>
		<description>Open Source PHP Content Management Framework</description>
		<generator>Cotonti</generator>
		<language>en</language>
		<pubDate>Sat, 04 Apr 2026 18:15:11 -0000</pubDate>

		<item>
			<title>Reading Time</title>
			<description><![CDATA[<p>Plugin Reading Time lets you add estimated page reading time to your Cotonti posts.</p><div><h2>Install and configure</h2></div><ol><li>Download plugin from the repository, unpack the contents and upload to the plugins folder of the remote server.</li><li>Configure plugin settings (field lists, reading speed &amp; optional tags) as needed.</li><li>Place TPL-tags in the templates.</li></ol><div><h2>TPL-tags generated by the plugin:</h2></div><p>All TPL-tags are included in the array produced by the <code>cot_generate_pagetags()</code> function:</p><ul><li>READING_TIME ("XX minutes" format)</li><li>READING_TIME_DIG ("XX" format)</li><li>READING_TIME_TXT ("minutes" format)</li></ul><div><h3>Additional pagetags:</h3></div><ul><li>LENGTH_META_TITLE (length of meta title)</li><li>LENGTH_META_DESC (length of meta description)</li><li>LENGTH_TITLE (length of page title)</li><li>LENGTH_DESCRIPTION (length of page description)</li><li>LENGTH_TEXT (length of page text)</li></ul><p>You can place those in the corresponding templates using prefixes PAGE_, PAGE_ROW_, LIST_ROW_ etc.</p>]]></description>
			<pubDate>Fri, 16 Jan 2026 09:49:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/reading-time]]></link>
		</item>
		<item>
			<title>CKEditor 4</title>
			<description><![CDATA[<p>Since Cotonti 0.9.26+ we are having CKEditor 5 in the box. Those of you guys who prefer to stick with version 4 can download it as a separate plugin using different name - ckeditor4. This way you will not overwrite it while applying officlal update where the folder with CKE5 is named 'ckeditor'.</p><p>Installation:</p><ol><li>Download, upload to the plugins folder and install via admin panel</li><li>Select ckeditor4 parser in the HTML Parser plugin config</li></ol>]]></description>
			<pubDate>Mon, 22 Dec 2025 11:12:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/ckeditor4]]></link>
		</item>
		<item>
			<title>Faker</title>
			<description><![CDATA[<h2>What is FakerPHP used for?</h2><p>The <a target="_blank" href="https://fakerphp.org/" rel="nofollow" rel="nofollow noreferrer noopener">FakerPHP library</a> is used to generate fake data for testing and debugging purposes via its properties called formatters. The Faker plugin utilizes the library to generate fake:</p><ul><li>pages.</li><li>comments.</li><li>user accounts.</li></ul><h2>Installation</h2><ol><li>Install FakerPHP via Composer: <code>composer require fakerphp/faker</code></li><li>Copy the 'faker' folder to your Cotonti plugins folder.</li><li>Install it via Administration / Extensions.</li><li>Configure path to FakerPHP and Locale via plugin config</li></ol><h2>Use</h2><p>The following options are available to generate fake pages:</p><ul><li>number of pages to create,</li><li>page title length,</li><li>page description length,</li><li>page_text length,</li><li>page section.</li></ul><p>Page date is set randomly between the first user registration date and the current date.</p><p>The following options are available to generate fake comments:</p><ul><li>number of comments to create,</li><li>comment text length.</li></ul><p>Comment date is set randomly between the first user registration date and the current date. Target page is selected randomly.</p><p>The following options are available to generate fake user accounts:</p><ul><li>number of accounts to create,</li><li>user group.</li></ul><h2>Credits</h2><ul><li>Francois Zaninotto for his <a target="_blank" href="https://github.com/fzaninotto/Faker" rel="nofollow" rel="nofollow noreferrer noopener">Faker</a> library</li><li>Twibie for the first Cotonti implementation</li></ul>]]></description>
			<pubDate>Sun, 14 Dec 2025 15:18:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/faker]]></link>
		</item>
		<item>
			<title>Top Tags</title>
			<description><![CDATA[<p>This is a simple plugin-function that is used to output most popular hashtags with the following options:</p><ol><li>Customizable output template</li><li>Variable number of hashtags</li><li>Optional caching</li></ol><p>Installation is simple:</p><ul><li>Download plugin</li><li>Upload it into the plugins folder</li><li>Install plugin from within the admin panel</li><li>Place callback function(s) &amp; customize output template(s)</li></ul><h2>Callback function</h2><p>The plugin outputs hashtags via <code>sedby_toptags()</code> function with the following arguments:</p><pre><code class="language-php">sedby_toptags($tpl = 'toptags', $items = 10, $tt_cache = '' $tt_ttl = 0)</code></pre><ul><li>$tpl defines template file (default toptags.tpl comes with the plugin package);</li><li>$items defines number of hashtags;</li><li>$tt_cache and $tt_ttl (if used together) turn on caching for the period of time in seconds specified by $tt_ttl.</li></ul><p>Note: the function can use memory cache only if it is enabled in the config.php:</p><pre><code class="language-php">$cfg['cache'] = true;</code></pre><p>Otherwise it will generate the output code each time the function is called.</p>]]></description>
			<pubDate>Fri, 28 Nov 2025 16:42:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/top-tags]]></link>
		</item>
		<item>
			<title>Varnish Cache plugin</title>
			<description><![CDATA[<p>Supercharge your Cotonti website with Varnish Cache integration! This plugin seamlessly connects your Cotonti CMS with Varnish Cache, a powerful HTTP accelerator that dramatically improves website performance and reduces server load. Features include auto.</p>

<p>Copy the unarchived file to /plugins/ in the root directory.</p>

<p>Go to the plugins section in the admin panel and activate Varnish Cache.</p>

<p> </p>

<p>Enter Varnish cache ports in plugin settings.</p>

<p>defaults:</p>

<p>Varnish host:127.0.0.0.1</p>

<p>Varnish admin port:80</p>

<p>Admin port:6082</p>

<p>Server port:6081</p>

<p><img alt="" height="583" src="https://raw.githubusercontent.com/slaweally/Cotonti-varnish-cache/refs/heads/main/varnish-1.png" width="720" /></p>

<p><img alt="" src="https://raw.githubusercontent.com/slaweally/Cotonti-varnish-cache/refs/heads/main/varnish-2.png" style="width:721px;height:900px;" /></p>

<p>Github page: <a href="https://github.com/slaweally/Cotonti-varnish-cache" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/slaweally/Cotonti-varnish-cache/</a></p>

<p>Author: Ali Çömez / Slaweally</p>
]]></description>
			<pubDate>Mon, 23 Jun 2025 12:37:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/performance-seo/Slaweally7892]]></link>
		</item>
		<item>
			<title>Reactions İcon</title>
			<description><![CDATA[<p><img alt="" src="https://www.cotonti.com/datas/users/reactions_12263.png" style="width:770px;height:77px;" /></p>

<p> </p>

<p><strong>Reactions plugin</strong> allows users to give emoji-based reactions to content on pages, forums and comments.</p>

<p>It offers fast installation and seamless integration thanks to its fully compatible structure with Cotonti infrastructure.<br />
Daily and per-user limit options.</p>

<p><strong>Installation:</strong><br />
Upload the downloaded file to the plugins folder -&gt; Admin Panel -&gt; Plugins -&gt; reactions -&gt; install</p>

<p>Then add the plugin tags where you want the reactions to appear (such as page - forum):<br />
Forums;<br />
<code>{FORUMS_POSTS_ROW_REACTIONS_BUTTONS}<br />
{FORUMS_POSTS_ROW_REACTIONS_COUNTS}</code></p>

<p>Pages;<br />
<code>{PAGE_REACTIONS_BUTTONS}<br />
{PAGE_REACTIONS_COUNTS}</code></p>

<p>You can make updates to the css file according to your request and adapt it to your own theme.</p>

<p> </p>
]]></description>
			<pubDate>Sun, 27 Apr 2025 10:23:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/addons/icons/Ali%20%C3%87%C3%B6mez]]></link>
		</item>
		<item>
			<title>Nexus</title>
			<description><![CDATA[<p>Cotonti theme Nexus. Modern and mobile-friendly.</p>

<p>Author: <a href="https://www.cotonti.com/users/Rootali">Rootali</a></p>

<p>Github: <a href="https://github.com/Cotonti-Themes/nexus" rel="nofollow">https://github.com/Cotonti-Themes/nexus</a></p>

<p><img alt="" src="https://i.imgur.com/WwGeg3a.png" /></p>

<h2><img alt="" src="https://i.imgur.com/zvz0pCz.png" /></h2>

<h2>Install</h2>

<ul>
	<li>Download and copy the "nexus" folder into the "themes" folder of your website.</li>
	<li>Set <code>$cfg['defaulttheme'] = 'nexus';</code> in the <strong>datas/config.php file</strong>.</li>
</ul>

<h3>Theme Github:</h3>

<p>Rootali: https://github.com/slaweallx/Nexus</p>

<p>Cotonti Theme: https://github.com/Cotonti-Themes/nexus</p>

<p><img alt="" src="https://private-user-images.githubusercontent.com/1021886/436355220-8bd47d4e-c41d-4929-99bb-6109a01e5d9c.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDUzODE4NDQsIm5iZiI6MTc0NTM4MTU0NCwicGF0aCI6Ii8xMDIxODg2LzQzNjM1NTIyMC04YmQ0N2Q0ZS1jNDFkLTQ5MjktOTliYi02MTA5YTAxZTVkOWMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDQyMyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTA0MjNUMDQxMjI0WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MDgzNTJkYTA3MzFlZWNjM2RiYzY3MDFhM2UwYmQ1NTcxMzlmMDA0OWYxNzM0YzU0ZDY1MWNkODc1Y2NkMWU1OCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.NlyRIjKkwsGZegRo8o1vpUuc1d1aK3Zlm7vUG-Ht3wo" /></p>
]]></description>
			<pubDate>Tue, 22 Apr 2025 11:22:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/themes/nexus]]></link>
		</item>
		<item>
			<title>Turkish (TR) Language Pack for Cotonti Siena</title>
			<description><![CDATA[<p>Turkish (TR) language pack for Cotonti Siena 0.9.25</p>

<p>Github: <a href="https://github.com/Cotonti-Langs/turkish" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Cotonti-Langs/turkish</a></p>

<p><br />
Please contact me by PM if you have any suggestions or corrections of this translation.<br />
<br />
Installation:<br />
1. Unpack the downloaded archive.<br />
2. Copy the folders from the archive to the root directory of your website.<br />
3. Open datas/config.php<br />
4. Find</p>

<div class="highlight">
<pre class="php">
$cfg['defaultlang'] = 'en';</pre>
</div>

<p>5.Replace</p>

<div class="highlight">
<pre class="php">
$cfg['defaultlang'] = 'tr';</pre>
</div>

<p> </p>
]]></description>
			<pubDate>Wed, 02 Apr 2025 04:38:43 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/locales/turkish-language-pack]]></link>
		</item>
		<item>
			<title>Cloudflare Turnstile</title>
			<description><![CDATA[<div class="markdown-heading">
<h2 class="heading-element">Features</h2>

<p><img alt="" src="https://raw.githubusercontent.com/SLW-CMS/Cotonti_Turnstile/refs/heads/main/cloudflare-turnstille.png" /></p>
</div>

<ul>
	<li>Protects user registration, login, and comments from spam bots.</li>
	<li>Simple integration into existing Cotonti forms.</li>
	<li>Admin-configurable through Cotonti admin panel.</li>
	<li>Modern and secure user verification without compromising user experience.</li>
</ul>

<div class="markdown-heading">
<h2 class="heading-element">Requirements</h2>
</div>

<ul>
	<li>Cotonti Siena v0.9.25 or later</li>
	<li>Cloudflare Turnstile Site Key and Secret Key (<a href="https://dash.cloudflare.com" rel="nofollow" rel="nofollow">Get keys here</a>)</li>
</ul>

<div class="markdown-heading">
<h2 class="heading-element">Installation</h2>
</div>

<ul>
	<li>
	<p>Upload the plugin folder <code>turnstile</code> into your Cotonti plugins directory: Setup is very simple, just add the following validation field to login and input fields like register, comment.</p>

	<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
	<pre class="notranslate">
<code>     &lt;!-- Cloudflare Turnstile Captcha --&gt;
     &lt;!-- IF {USERS_AUTH_VERIFY_IMG} --&gt;
     &lt;tr&gt;
         &lt;td colspan="2" class="textcenter"&gt;
             {USERS_AUTH_VERIFY_IMG}
             {USERS_AUTH_VERIFY_INPUT}
         &lt;/td&gt;
     &lt;/tr&gt;
     &lt;!-- ENDIF --&gt;
</code></pre>

	<p> </p>

	<p>Github: <a href="https://github.com/SLW-CMS/Cotonti_Turnstile/" rel="nofollow" rel="nofollow">Cloudflare Turnstile Plugin</a></p>

	<p>Plugin Page: <a href="https://rootali.net/cloudflare-turnstile-plugin-for-cotonti-siena.slw" rel="nofollow" rel="nofollow">Cotonti Cloudflare Turnstile Plugin</a></p>
	</div>
	</li>
</ul>
]]></description>
			<pubDate>Sat, 08 Mar 2025 05:12:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/security-authentication/Slaweally]]></link>
		</item>
		<item>
			<title>Accepting payments</title>
			<description><![CDATA[<h2>Accepting payments.</h2>

<p>When developing e-commerce extensions, such as an online store, paid services or consultations, etc., you need to arrange payment acceptance, which will be convenient to use.</p>

<p>This can be implemented using the <a href="https://github.com/Cotonti-Extensions/freelance/tree/master/modules/payments" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">"Payments"</a> module.</p>

<p>This module can be integrated with any online payment system: PayPal, UKassa, bank payment systems, etc.<br />
To create a payment, add the following code in the controller of your extension after the order is generated:</p>

<pre class="brush:php;">
$amount = 500; // Payment amount. Pennies are transferred as a fractional part.
$area = 'orderType'; // type of payment (order or service code)
$options = [
    // Optional. When paying for periodic services, if the period is not stored 
    // in your extension, the expiration date of the paid service can be stored 
    // in this field.
    'time' =&gt; $months * 30 * 24 * 60 * 60,
    
    // Optional. Description or purpose of the payment.
    'desc' =&gt; 'Order description',
    
    // Optional. The order ID on the side of the extension being developed or the user ID.
    // Can be used to identify the payment by your extension.
    'code' =&gt; $orderId,
    
    // Optional. Where to redirect the user after successful payment.
    // If not specified, the user will be redirected to their payment history.
    // https://domain.tld/payments?m=balance&amp;n=history
    'redirect' =&gt; cot_url('extension-code', ['m' =&gt; 'orders', 'id' =&gt; $orderId], '', true)
]

cot_payments_create_order($area, $amount, $options);</pre>

<p>A pair of values <code>$area</code> and <code>$options['code']</code> should uniquely identify the payment so that your extension can correctly automatically activate the paid service after payment.</p>

<p>The <code>cot_payments_create_order()</code> function will create a payment and redirect the user to the payment page, where the user will be able to select one of the installed payment system plugins and make a payment.</p>

<p><img alt="" src="https://www.cotonti.com/datas/users/payment-select_0.png" /></p>

<p>After making the payment, the user will be redirected to a page with his payments history and there will be shown a message about a successful payment or an error.</p>

<p><img alt="Payments" src="https://www.cotonti.com/datas/users/payment-success_0.png" /></p>

<p>If the <code>$options['redirect']</code>, parameter was passed when creating the payment, then in case of successful payment, user will be redirected to the specified url.</p>

<p>At the moment when the payment status changes to <strong>"Paid"</strong> the <strong>payments.payment.success</strong> hook is triggered.<br />
Your extension should handle this hook to automatically activate the paid service. An array with payment data is available to the hook handler. This is an array with data from the <strong>cot_payments</strong> table containing the payment record being processed..</p>

<p>Please note that this hook is usually called at the moment when the payment system calls the web-hook with payment notification. The request is made from the  payment system's server  and the user making the payment has nothing to do with this request and the session of this user is unavailable at this moment. Therefore, the handler of this hook should not output any data or headers and should not make any redirects.</p>

<p>To display any information to the user, you need to use the URL passed through <code>$options['redirect']</code>, if the standard one is not enough. Usually, when a user goes on this URL, the payment has already been processed and the result can be displayed to the user.</p>

<p>To test your extension integration with the payment module, you can use the <a href="https://github.com/Cotonti-Extensions/freelance/tree/master/plugins/nullbilling" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Nullbilling</a> plugin. It is a plugin with a test payment system that does not make any payments, but simulates a successful payment.</p>

<h2>Connecting payment systems</h2>

<p>You can add a new payment system by installing the appropriate plugin. If there is no ready-made one, then you can write your own.</p>

<p>Let's consider creating such a plugin.</p>

<p>The plugin must register itself as a payment system plugin. To do this, it must process the <strong>payments.billing.register</strong> hook and add its data to the <code>$cot_billings</code> array. For example, like this:</p>

<pre class="brush:php;">
if (
    Cot::$cfg['plugin']['myPaymentSystem']['on']
    &amp;&amp; !empty(Cot::$cfg['plugin']['myPaymentSystem']['apiKey'])
    &amp;&amp; !empty(Cot::$cfg['plugin']['myPaymentSystem']['secret'])
) {
    $cot_billings['myPaymentSystem'] = [
        'plug' =&gt; 'myPaymentSystem',
        'title' =&gt; Cot::$L['tbank_title'],
        'icon' =&gt; Cot::$cfg['plugins_dir'] . '/myPaymentSystem/images/logo.png',
    ];
}</pre>

<p>If the payment system sends payment notification (web-hook) using the POST method, it is necessary to disable xss protection for the web-hook handler, otherwise Cotonti will not accept the request from the payment system. To do this, you need to make the <strong>input</strong> hook handler with the following code:</p>

<pre class="brush:php;">
if (
    isset($_GET['e'])
    &amp;&amp; $_GET['e'] === 'myPaymentSystem'
    &amp;&amp; isset($_GET['a'])
    &amp;&amp; $_GET['a'] === 'notify'
    &amp;&amp; $_SERVER['REQUEST_METHOD'] === 'POST'
) {
    define('COT_NO_ANTIXSS', 1) ;
    Cot::$cfg['referercheck'] = false;
}</pre>

<p>Add $_GET parameters for which the payment notification (web-hook) handler is available to the if condition.</p>

<p>The plugin has a <strong>standalone</strong> hook handler, but it does not output any data to the user, but uses it for other purposes. The "Open" button for this plugin is not needed in the admin panel in the list of extensions. Let's put it away. To do this, add the code to the <strong>admin.extensions.plug.list.loop</strong> hook handler:</p>

<pre class="brush:php;">
if ($type === COT_EXT_TYPE_PLUGIN &amp;&amp; $code === 'myPaymentSystem') {
    $t-&gt;assign([
        'ADMIN_EXTENSIONS_JUMPTO_URL' =&gt; null,
    ]);
}</pre>

<p>And to <strong>admin.extensions.details</strong> hook:</p>

<pre class="brush:php;">
if ($type === COT_EXT_TYPE_PLUGIN &amp;&amp; $code === 'myPaymentSystem') {
    $standalone = null;
    $t-&gt;assign([
        'ADMIN_EXTENSIONS_JUMPTO_URL' =&gt; $standalone,
    ]);
}</pre>

<p>If you need to display any reference information for the site administrator on the plugin settings page in the admin panel, for example, the settings that need to be made in the personal account of the payment system itself, use the <strong>admin.config.edit.tags</strong> hook</p>

<pre class="brush:php;">
if ($o === COT_EXT_TYPE_PLUGIN &amp;&amp; $p === 'myPaymentSystem') {
    $adminHelp = '... Справка по настройке платежной системы ...';
}</pre>

<p>And will make the standalone hook handler. It solves 2 tasks, depending on the passed parameters:</p>

<p>1) On the payment method selection page, when clicking on the payment system link, the user is redirecting to this page. The GET parameter pid  contains the local payment ID in the <strong>cot_payments</strong> table.</p>

<p>Get the payment data:</p>

<pre class="brush:php;">
// Get <span style="white-space:pre-wrap;">payment ID</span>
$paymentId = cot_import('pid', 'G', 'INT');
if (!$paymentId) {
    cot_die_message(404);
}

// Get pyment data from DB
$payment = PaymentRepository::getById($paymentId);
if (!$payment) {
    cot_die_message(404);
}

// Check if the payment status allows to make a payment
cot_block(in_array($payment['pay_status'], PaymentDictionary::ALLOW_PAYMENT_STATUSES, true));</pre>

<p>The further scenario depends on the API of the payment system. It usually consists of the following: send a request to the payment system to initialize the payment on its side. In response, the payment system returns the URL to which the user must be redirected to make the payment.</p>

<p>Many payment systems allow to transfer URLs in the payment initialization parameters, where needed to redirect the user after payment. <span style="white-space:pre-wrap;">You can get them using the following methods</span>: successful payment url - <code>PaymentService::getSuccessUrl($PaymentId)</code> and the fail payment URL - <code>PaymentService::getFailUrl($paymentId)</code>.</p>

<p><span style="white-space:pre-wrap;">Before redirecting the user to the payment system's website to make a payment, set the local payment status "<strong>In progress</strong>" and specify which payment system processes the payment.</span></p>

<pre class="brush:php;">
PaymentService::setStatus(
    $paymentId,
    PaymentDictionary::STATUS_PROCESS,
    'myPaymentSystem',
    PaymentDictionary::METHOD_CARD,
    $psPaymentId
);</pre>

<p>The last 2 parameters are optional. The penultimate one indicates that the payment will be made with bank card, and the last one is the payment identifier passed to the payment system.</p>

<p>Some payment systems require you to pass a unique payment ID each time. And in the case when the payment failed and the user tries to pay again, the old payment ID is no longer accepted. For such payment systems, your plugin must generate a unique payment ID. For example, like this:</p>

<pre class="brush:php;">
$psPaymentId = $paymentId . '-' . time();</pre>

<p>We save it in the cot_payments table, passing the 5th parameter to <code>PaymentService::setStatus()</code>.</p>

<p>2) When a user makes a payment on the payment system's website, before returning the user back to your site, the payment system sends a payment notification (web hook) with the payment status. It needs to be processed. There is no need to do this in the <strong>standalone</strong> hook, you can also do it in the <strong>ajax</strong> hook.</p>

<p>When the notification from the payment system has been processed and the checks have been completed in accordance with the documentation for the payment system, it is necessary to set the local payment status to the "<strong>Paid</strong>"</p>

<pre class="brush:php;">
PaymentService::setStatus(
    $paymentId,
    PaymentDictionary::STATUS_PAID,
    'myPaymentSystem',
    null,
    null,
    $transactionId
)</pre>

<p>here we skip the parameters <code>$paymentMethod</code>, <code>$paymentSystemPaymentId</code> - they were set earlier. But we pass <code>$transactionId</code> (optional) - the identifier of the transaction (or payment) on the payment system side. Most payment systems pass it with payment notification (web-hook).</p>
]]></description>
			<pubDate>Mon, 07 Oct 2024 18:16:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/docs/devel/accepting-payments]]></link>
		</item>
		<item>
			<title>Using captcha in extensions</title>
			<description><![CDATA[<p>When developing an extension, it is often necessary to display some form to unregistered users: a feedback form, "order a call", ask a question to support, etc. Such forms can be filled out and sent to the server by spam bots, thereby filling the database with garbage. A captcha is a very effective way to protect against such bots.</p>

<p>It makes no sense to require registered users to fill out a captcha because bots cannot log in to the site and "spam" all forms. Therefore, you need to display the captcha only in those forms that can be filled by the guests.</p>

<p>Using a captcha in your extensions is pretty simple.</p>

<p>To display a captcha in any form:</p>

<p>Add such code to the your extension's controller:</p>

<pre class="brush:php;">
// Initialize the template engine
$t = new XTemplate($pathToTemlateFile);

// ... some code of your extension ...

// Check if user is not logged in and at least one captcha is installed on the site:
if (Cot::$usr['id'] === 0 &amp;&amp; !empty($cot_captcha)) {
	// Output captcha to the template
	$t-&gt;assign(cot_generateCaptchaTags(null, 'rverify', 'FEEDBACK_FORM_'));
}</pre>

<p>Add tags to the template for captcha output:</p>

<pre class="brush:xml;">
&lt;!-- IF {FEEDBACK_FORM_VERIFY_IMG} --&gt;
&lt;div&gt;
	{FEEDBACK_FORM_VERIFY_IMG} {FEEDBACK_FORM_VERIFY_INPUT}
&lt;/div&gt;	
&lt;!-- ENDIF --&gt;</pre>

<p>And finally, when processing the data sent by the user, you need to check whether the captcha is filled in correctly:</p>

<pre class="brush:php;">
if (Cot::$usr['id'] === 0 &amp;&amp; !empty($cot_captcha)) {
	$rverify = cot_import('rverify', 'P', 'TXT');
	if (!cot_captcha_validate($rverify)) {
		// The captcha is not filled correctly
		cot_error('captcha_verification_failed', 'rverify');
	}
}</pre>
]]></description>
			<pubDate>Mon, 07 Oct 2024 04:56:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/docs/ext/extensions/using-captcha]]></link>
		</item>
		<item>
			<title>SecurImage Captcha</title>
			<description><![CDATA[<p><img alt="" src="https://private-user-images.githubusercontent.com/1021886/371828036-3c3fbf59-e17d-4047-8df1-52e30aa9ed5d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjgxOTI5MDgsIm5iZiI6MTcyODE5MjYwOCwicGF0aCI6Ii8xMDIxODg2LzM3MTgyODAzNi0zYzNmYmY1OS1lMTdkLTQwNDctOGRmMS01MmUzMGFhOWVkNWQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MTAwNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDEwMDZUMDUzMDA4WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9Njc4NDc2YjExOTJkYzk5MzFhMjY0NTUwOGFiNGNkZDRkYTdmOTQ0MDFmN2ZmOGZiMGM0Zjc5N2Q2NDNiMjc3NiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.Sc1JV3VCliB-ZAu7qKCvAckx8tvNQ2AoE4h6YSFFKKQ" /></p>

<p>Securimage CAPTCHA plugin for Cotonti CMF. Protects your site from spam bots with image captcha.</p>

<p>Uses the <a href="https://github.com/dapphp/securimage" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Securimage class</a> (from <a href="https://github.com/dapphp" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Drew Phillips</a>)</p>

<p>Authors:</p>

<ul>
	<li>Securimage <a href="https://github.com/dapphp" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Drew Phillips</a></li>
	<li>Cotonti plugin: <a href="https://www.cotonti.com/users/Alex300" target="_blank" rel="nofollow noreferrer noopener">Alexey Kalnov</a> (<a href="https://github.com/Alex300" rel="nofollow" rel="nofollow">https://github.com/Alex300</a>)</li>
</ul>

<p>Github: <a href="https://github.com/Alex300/SecurImageCaptcha-for-Cotonti" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Alex300/SecurImageCaptcha-for-Cotonti</a></p>

<p>Plugin page on author's site: <a href="https://lily-software.com/free-scripts/cotonti-securImage-captcha" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://lily-software.com/free-scripts/cotonti-securImage-captcha</a></p>

<h2>Opportunities:</h2>

<ul>
	<li>You can use this captcha wherever it is used on your site: in the registration form, comments, feedback, etc.</li>
	<li>The image can be updated without reloading the page</li>
	<li>Those who cannot read the code can listen to the voice code</li>
</ul>

<p>A sample of the captcha's work can be viewed, for example, in the <a href="https://lily-software.com/users?m=register" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">registration form of this site</a>.</p>

<h2>Installation:</h2>

<ul>
	<li>copy the captcha folder from the archive to the plugins folder on your hosting</li>
	<li>install the plugin in the ite admin panel</li>
	<li>in the site admin panel, under <strong>Configuration</strong> -&gt; <strong>Security</strong> -&gt; <strong>Captcha</strong>, select default "Captcha"</li>
</ul>

<p>To change the image settings (font, size, background image, noises, etc.), edit the file <strong>/inc/imageshow.php</strong></p>

<h2>Using captchas in your plugins:</h2>

<p><a href="https://www.cotonti.com/docs/ext/extensions/using-captcha-in-extensions">Similar to using any other captcha</a>.</p>

<p> </p>
]]></description>
			<pubDate>Sun, 06 Oct 2024 05:33:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/security-authentication/securImage-captcha]]></link>
		</item>
		<item>
			<title>Freelance Exchange bundle</title>
			<description><![CDATA[<p>Freelance Exchange bundle for CMF Cotonti. With this bundle, you can organize any exchange to search for performers for various jobs. Its  functionality provides flexible options for operation and further development.</p>

<p>Authors: <a href="https://github.com/devkont" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Bulat Yusupov</a> и CMSWorks team, Cotonti team<br />
GitHub: <a href="https://github.com/Cotonti-Extensions/freelance" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Cotonti-Extensions/freelance</a></p>

<h2>Main features</h2>

<p>User accounts with their personal pages (contact information is displayed on the personal page, as well as lists of published projects, works in the portfolio and in the marketplace); Catalog of jobs (job projects), the ability to publish jobs. Jobs search with filtering by region and keywords; Catalog of freelancers and employers sorted by specialization; Payment module with internal user accounts and the ability to replenish and pay for services; Included payment systems: <a href="https://interkassa.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Interkassa</a>, <a href="https://robokassa.com" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Robokassa</a> and WebMoney (separate plugins) and the ability to easily connect other payment systems; Paid service "PRO account"; Paid service "Paid place on the main page" (Users who have paid for this service are displayed on the main page of the exchange); Secure payment service; Reviews and ratings.</p>

<p><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">Extensions</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> from </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">this </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">bundle </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">can</span><span style="white-space:pre-wrap;"> be </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">installed </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">on </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">existing </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">sites </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">and </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">used </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">individually</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> and </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">only </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">those ones</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> that</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> you</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> need</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">.</span></p>

<p>Or you can prepare a "build" that will use the built-in Cotonti installer to selectively install extensions from this bundle with the standard Cotonti extensions. <span style="white-space:pre-wrap;">This particular option is described below</span>.</p>

<h2><span style="white-space:pre-wrap;">Preparing for install</span></h2>

<p>This is not a ready to use website build. To install it, you need the current version of CMF Cotonti, which can be downloaded in the <a href="https://www.cotonti.com/download">Download section</a>.</p>

<ul>
	<li>Download Cotonti. Unpack the archive into the directory of the future site.</li>
	<li>Download Freelance Exchange bundle and unpack it into the same directory in which Cotonti is unpacked.</li>
	<li>Set the write permissions for folders and subfolders in the <strong>/data</strong> directory: <strong>/datas/avatars</strong>, <strong>/data/cache</strong> (and all subfolders), <strong>/datas/extflds</strong>, <strong>/datas/photos</strong>, <strong>/datas/thumbs</strong>, <strong>/datas/users</strong></li>
</ul>

<h2>Install</h2>

<ul>
	<li>Open your browser and follow the link: <strong>http://your-domain.tld/install.php</strong> (replace <strong>your-domain.tld</strong> with your domain)</li>
	<li>Follow the on-screen instructions until the installation is complete. During installation, select the <strong>flance</strong> installation script and <strong>bootlance</strong> theme.</li>
	<li>During installation, you will be prompted to select modules and plugins. The most basic extensions that are necessary for the operation of the exchange are ticked, but you can also select the rest if necessary.</li>
	<li>In the file <strong>datas/config.php</strong> set the option <code>$cfg['customfuncs'] = true;</code></li>
	<li>Be sure to configure the <strong>Usergroupselector</strong> plugin if your site will divide users into different groups, for example, employers and freelancers. In the settings of this plugin, you need to specify which groups will be available for users to choose when registering or in the profile. If you need to create another user group, then go to the "Users" section of the admin panel.</li>
	<li>In order to be able to attach files and images to projects (as well as to suggestions in the description and in the portfolio), you must also install the <strong>Mavatars</strong> and <strong>Mavatarslance</strong> plugins, which also come as part of the bundle.</li>
	<li>Initially, your site will be empty. You can create your own categories yourself in the "Structure" section of the admin panel.</li>
</ul>

<h2><span style="white-space:pre-wrap;">Learn more about the possibilities of the Freelance Exchange</span> bundle</h2>

<h3>Jobs</h3>

<p><span style="white-space:pre-wrap;"><a href="https://github.com/Cotonti-Extensions/freelance/tree/master/modules/projects" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Projects</a> module</span></p>

<p><span style="white-space:pre-wrap;">Any user can publish their job project on the site. In the job project, you can specify the location, city, price, section in the catalog (area of activity), the title of the project and its description. You can also attach various files to the project description. Freelancers who are interested in the published job can leave their suggestions on the job project page. The employer can choose the contractor or refuse the project to any Freelancer who left an offer. An employer or Freelancer who has submitted a job project proposal can correspond directly on the project page.</span></p>

<h3><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">Marketplace</span></h3>

<p><a href="https://github.com/Cotonti-Extensions/freelance/tree/master/modules/market" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Market</a> module<br />
<span style="white-space:pre-wrap;">A </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">section</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">for</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">placing</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">ready</span><span style="white-space:pre-wrap;">-</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">to</span><span style="white-space:pre-wrap;">-</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">sell</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">goods</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">or</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">services</span><span style="white-space:pre-wrap;"> of the </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">user</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">.</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">Each</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">product</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">contains</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">:</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">title</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">,</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">description</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">,</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">image</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">and</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">price</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">.</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;"> Also</span><span style="white-space:pre-wrap;">, </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">all</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">products</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">/</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">services</span><span style="white-space:pre-wrap;"> are </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">categorized</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">in</span><span style="white-space:pre-wrap;"> the </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">catalog</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">for</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">easy</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">search</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">.</span></p>

<h3><span style="white-space:pre-wrap;">Accepting payments</span></h3>

<p><a href="https://github.com/Cotonti-Extensions/freelance/tree/master/modules/payments" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Payments</a> module</p>

<p class="CPO0LE0j16AwB0G2HeuZ" dir="ltr"><span style="white-space:pre-wrap;">This module is a universal mechanism that allows you to accept payments on your site. </span></p>

<p class="CPO0LE0j16AwB0G2HeuZ" dir="ltr"><span style="white-space:pre-wrap;">Payments are accepted through <a href="https://robokassa.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Robokassa</a>, <a href="https://interkassa.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Interkassa</a> and WebMoney systems. Connecting other payment systems should not cause serious difficulties for developers. </span></p>

<p class="CPO0LE0j16AwB0G2HeuZ" dir="ltr"><span style="white-space:pre-wrap;">You can use this module to accept payments in your extensions. </span></p>

<p class="CPO0LE0j16AwB0G2HeuZ" dir="ltr"><span style="white-space:pre-wrap;">In addition, optionally, each user can have their own personal account on the site with which they can pay for paid services.</span></p>

<h3><span style="white-space:pre-wrap;">Users Portfolios</span></h3>

<p><a href="https://github.com/Cotonti-Extensions/freelance/tree/master/modules/folio" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Folio</a> module<br />
<span style="white-space:pre-wrap;">Allows users to exhibit their work as a portfolio. Optionally, the works can be pre-moderated before publication.</span></p>

<h3><span style="white-space:pre-wrap;">Secure settlement system (Risk-free transactions)</span></h3>

<p><a href="https://github.com/Cotonti-Extensions/freelance/tree/master/plugins/sbr" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Sbr</a> plugin<br />
<span style="white-space:pre-wrap;">The plugin allows you to organize on the Freelance Exchange website the opportunity for users to make transactions with each other with full coordination of all stages of work. In this case, the transaction budget is reserved on the website account before the start of all work and is paid to the Contractor after acceptance of the results of work on each stage of the transaction. In case of disputes, either party may contact the arbitration commission (the site administration). The Arbitration commission, by analyzing the internal correspondence on the transaction, makes an appropriate decision on the payment of the work performed to the Contractor, or on the return of the budget for the stage of the transaction to the Customer. The commission may also decide on a partial payment to the parties. In this way, all parties to the transaction are protected.</span></p>

<h3><span style="white-space:pre-wrap;">User roles (groups)</span></h3>

<p><span style="white-space:pre-wrap;">There are two parties involved in the traditional freelance exchange, these are freelancers and customers. But we've improved the system a bit and added the ability to expand the number of service members. Now you can create your own roles on the site and link them to user groups for which you can configure access rights to all sections of the site and define your capabilities for them.</span></p>

<h3><span style="white-space:pre-wrap;">Reviews</span></h3>

<p><span style="white-space:pre-wrap;">Any user of the service can leave feedback to other participants. The review can be either positive or negative, to choose from. Access to the publication of Reviews can be limited only within the framework of completed projects (configurable). By default, users can leave feedback to other users. If necessary, the feedback system can be configured so that reviews can be left only for completed orders, i.e., linked to the project.</span></p>

<h3><span style="white-space:pre-wrap;">User's ratings</span></h3>

<p><span style="white-space:pre-wrap;">In order to identify the most active users among the service participants, a rating system is functioning on the site. Whoever has a higher rating, that user is more visible on the site. </span></p>

<p><span style="white-space:pre-wrap;">How points are awarded (default settings): For visiting the site: +1 point, For placing work in the portfolio: +5 points, For the status of the contractor for the project: +1 point, For receiving a rejection for the project: -1 point, For receiving a positive review: +20 points, For receiving a negative review: -20 points, For the purchase of a PRO account: +20% to the rating, For the purchase of a paid place on the main page: +20% to the rating. The specified points values can be changed in the site admin panel. The ability to display top users anywhere on the site has also been added.</span></p>

<h3><span style="white-space:pre-wrap;">Paid services</span></h3>

<p><span style="white-space:pre-wrap;"><strong>PRO (premium) account</strong> (price per month). A PRO account gives you the opportunity to stand out among other exchange participants with a special icon, as well as priority placement in the catalog of freelancers (employers); <strong>A paid place on the main page</strong> and in any other place on the site (price per placement). <strong>Ad blocks</strong> can be placed anywhere on the site and set different prices for the size of them. Placement takes place by shifting previously paid and for a period of 1 month. Prices can also be changed in the admin panel.</span></p>

<h3><span style="white-space:pre-wrap;">Categories</span></h3>

<p>The site's admin panel allows you to edit categories for all parts of the site, including:<span style="white-space:pre-wrap;"> Categories of projects, types of projects (for example: Regular, Vacancies, etc.), categories of freelancers, categories in the marketplace, categories of information pages of the site. </span></p>
]]></description>
			<pubDate>Tue, 24 Sep 2024 16:40:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/commerce/freelance-bundle]]></link>
		</item>
		<item>
			<title>Database</title>
			<description><![CDATA[<h2>Introduction</h2>

<p>Almost any web application interacts with a database. Cotonti makes this interaction simple and comprehensive.</p>

<blockquote>
<p>Currently support is provided for MySQL 5.1+</p>
</blockquote>

<h2>Configuration</h2>

<p>The database connection configuration is located in the application's configuration file <strong>datas/config.php</strong>. It is filled in automatically during Cotonti installation.</p>

<h2>Running SQL Queries</h2>

<p>You can get access to the Cotonti database connection instance with the facade class <code>Cot</code>. The Cotonti database object is built on top of the <a href="https://www.php.net/manual/en/book.pdo.php" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PDO</a> and provides method for executing database queries and methods that simplify the construction of <code>INSERT</code>, <code>UPDATE</code> and <code>DELETE</code> queries.</p>

<p>You can execute a SQL query by taking the following steps:</p>

<ol>
	<li>Create a plain SQL query;</li>
	<li>Bind parameters (optional);</li>
	<li>Call one of the SQL execution methods in <a href="https://www.php.net/manual/en/class.pdostatement.php" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PDOStatement</a> class.</li>
</ol>

<p>The following example shows various ways of fetching data from a database:</p>

<pre class="brush:php;">
// Return a set of rows. Each row is an associative array of column names and values.
// an empty array is returned if the query returned no results
$posts = Cot::$db-&gt;query('SELECT * FROM post')-&gt;fetchAll();

// Return a single (first or next) row from a result set
// False is returned if the query has no result
$post = Cot::$db-&gt;query('SELECT * FROM post WHERE id=?', 1)-&gt;fetch();

// Returns a single column from the next row of a result set
// Or false if there are no more rows.
$titles = Cot::$db-&gt;query('SELECT title FROM post')-&gt;fetchColumn();
$count = Cot::$db-&gt;query('SELECT COUNT(*) FROM post')-&gt;fetchColumn();</pre>

<p>For queries that do not return data, you should call the <a href="https://www.php.net/manual/en/pdostatement.execute.php" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PDOStatement::execute()</a> method instead. For example:</p>

<pre class="brush:php;">
Cot::$db-&gt;query('UPDATE post SET status=1 WHERE id=1')-&gt;execute();</pre>

<p>For <code>INSERT</code>, <code>UPDATE</code> and <code>DELETE</code> queries, instead of writing pure SQL, you can call the <code>insert()</code>, <code>update()</code>, <code>delete()</code> methods, respectively, to create the specified SQL constructs. For example:</p>

<pre class="brush:php;">
// INSERT (table_name, column_values)
Cot::$db-&gt;insert(
    'posts', 
    [
        'titlle' =&gt; 'Lorem ipsum', 
        'text' =&gt; 'Morbi imperdiet tortor ut nisl ultricies finibus',
    ]
);
$newPostId = Cot::$db-&gt;lastInsertId();

// UPDATE (table_name, column_values, condition, params)
$condition = [
	"created_at &lt; '" . date('Y-m-d H:i:s', time() - 3600) . "'",
	'category = :category',
];
$updatedRowsCount = Cot::$db-&gt;update(
    'posts', 
    ['status' =&gt; 1], 
    $condition, 
    ['category' =&gt; $category]
);

// DELETE (table_name, condition, params)
$deletedRowsCount = Cot::$db-&gt;delete(
    'posts', 
    'status = 0 AND category = ?', 
    $category
);</pre>

<p><code>insert()</code>, <code>update()</code> and <code>delete()</code> methods do not require escaping the table name. This will be done automatically.</p>

<p><code>insert()</code> and <code>update()</code> methods do not require escaping array elements with data for insert/update.</p>

<p><code>update()</code> and <code>delete()</code> methods accept a condition that can be a string with an SQL condition or an array of strings. In the case of an array, each string will be wrapped in parentheses and they are combined with the AND operator.</p>

<p>In the example above:</p>

<pre class="brush:php;">
$condition = [
	"created_at &lt; '2024-07-08 12:45:56'",
	'category = :category'
];</pre>

<p>is equivalent to:</p>

<pre class="brush:php;">
(created_at &lt; '2024-07-08 12:45:56') AND (category = :category)</pre>

<h3>Binding Parameters</h3>

<p>When creating a SQL query with parameters, you should almost always use parameter binding to prevent SQL injection attacks. For example:</p>

<pre class="brush:php;">
$post = Cot::$db-&gt;query(
	'SELECT * FROM post WHERE category = ? AND status = ?',
	[$category, status]
)-&gt;fetch();</pre>

<p>When executing the query, each question mark in accordance with its order will be safely replaced with the corresponding value from the array.</p>

<p>If the request has only one parameter, you can pass a scalar value instead of an array:</p>

<pre class="brush:php;">
$post = Cot::$db-&gt;query('SELECT * FROM post WHERE category = ?', $category)-&gt;fetch();</pre>

<p>You can use scalar parameters:</p>

<pre class="brush:php;">
$post = Cot::$db-&gt;query(
	'SELECT * FROM post WHERE id = :id AND status = :status',
	['id' =&gt; $id, ':status' =&gt; status]
)-&gt;fetch();</pre>

<h3>Quoting Table and Column Names</h3>

<pre class="brush:php;">
Cot::$db-&gt;query(
    'SELECT * FROM ' . Cot::$db-&gt;quoteTableName(Cot::$db-&gt;pages) 
    . ' WHERE page_cat = ' . Cot::$db-&gt;quote($category)
)-&gt;fetchColumn();</pre>

<p>Quoting methods:</p>

<ul>
	<li><code>Cot::$db-&gt;quoteTableName()</code> or short version (<code>Cot::$db-&gt;quoteT()</code>)<br />
	Quotes a table name for use in a query. If the table name contains schema prefix, the prefix will also be properly quoted.</li>
	<li><code>Cot::$db-&gt;quoteColumnName()</code> or short version (<code>Cot::$db-&gt;quoteC()</code>)<br />
	Quotes a column name for use in a query. If the column name contains prefix, the prefix will also be properly quoted. If the column name is already quoted then this method will do nothing.</li>
	<li><code>Cot::$db-&gt;quote()</code><br />
	Quotes a string value for use in a query. It is recommended to use parameter binding instead of this method, if possible.</li>
</ul>

<h2>Database Transactions</h2>

<p>You may use the <code>Cot::$db-&gt;transaction()</code> method to run a set of operations within a database transaction. If an exception is thrown within the transaction closure, the transaction will automatically be rolled back and the exception is re-thrown. If the closure executes successfully, the transaction will automatically be committed. You don't need to worry about manually rolling back or committing while using the transaction method:</p>

<pre class="brush:php;">
Cot::$db-&gt;transaction(
	function(): void 
	{
		Cot::$db-&gt;update('posts', ['status' = 1], 'category = ?', $category);
		Cot::$db-&gt;delete('posts', 'status = 0']);
		// ... executing other SQL statements ...
	}
);</pre>

<h3>Manually Using Transactions</h3>

<p>You can use transactions manually and have complete control over commits and rollbacks and error handling. The example above is equivalent to this:</p>

<pre class="brush:php;">
Cot::$db-&gt;beginTransaction();
try {
    Cot::$db-&gt;update('posts', ['status' = 1], 'category = ?', $category);
    Cot::$db-&gt;delete('posts', 'status = 0']);
	// ... executing other SQL statements ...
    
    Cot::$db-&gt;commit();
} catch(\Throwable $e) {
    Cot::$db-&gt;rollBack();
	throw $e;
}</pre>

<h3>Specifying Isolation Level</h3>

<p>Cotonti supports setting isolation levels for your transactions. By default, when starting a new transaction, it will use the default isolation level set by your database system. You can override the default isolation level as follows:</p>

<pre class="brush:php;">
$isolationLevel = \cot\database\DataBaseDictionary::REPEATABLE_READ;

Cot::$db-&gt;transaction(
	function(): void 
	{
		....
	},
	$isolationLevel
);
 
// or

Cot::$db-&gt;beginTransaction($isolationLevel);</pre>

<h3>Handling Deadlocks</h3>

<p>The <code>Cot::$db-&gt;transaction()</code> method accepts an optional third argument which defines the number of times a transaction should be retried when a deadlock occurs. Once these attempts have been exhausted, an exception will be thrown:</p>

<pre class="brush:php;">
Cot::$db-&gt;transaction(
	function(): void 
	{
		....
	},
	$isolationLevel,
	5
);</pre>

<h2>Working with Database Schema</h2>

<p>(section being updated)</p>

<p>Cotonti database object provides several methods to work with database schema:</p>

<ul>
	<li><code>tableExists($tableName)</code> - check if table exists</li>
	<li><code>fieldExists($tableName, $fieldName)</code> - check if fieild exists</li>
	<li><code>indexExists($tableName, $indexName, $indexColumns = [])</code> - check if index exists</li>
	<li><code>addIndex($tableName, $indexName, $indexColumns = [])</code> - create Index. Here <code>$indexColumns</code> is either a string for a single column name or an array for single/multiple columns. <code>$indexName</code> will be used if empty.</li>
</ul>

<h2>Execution of SQL scripts</h2>

<p>The <code>CotDB::runScript($script, $translaction = false)</code> method allows you to execute SQL scripts (contents of SQL files). Table names must be escaped with the MySQL escape symbol <code>`</code> and have the <code>cot_</code> prefix, which will be replaced with the prefix from the settings in <strong>datas/config.php.</strong></p>
]]></description>
			<pubDate>Sun, 08 Sep 2024 14:51:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/docs/devel/database]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.25 released</title>
			<description><![CDATA[<p>This is a stability release that fixes bugs found after the release of 0.9.24. It is also a preparation before the 1.0 release.</p>

<p><strong>Whats new:</strong></p>

<ul>
	<li>Support for Php 5.x has been discontinued. The minimum Php version is <strong>7.3</strong></li>
	<li>Database: <strong>transactions support</strong> with nesting control</li>
	<li><code>cot_user_sqlExcludeBanned()</code> for generate sql condition to exclude banned users. You can use it your extensions.</li>
	<li><code>cot_generateCaptchaTags()</code> captcha tag generation unification for the coTemplate</li>
	<li><strong>Legacy mode</strong> (<code>$cfg['legacyMode']</code>) to turn on deprecated features. <span style="white-space:pre-wrap;">You </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">can </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">use</span><span style="white-space:pre-wrap;"> it </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">if </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">your </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">extensions </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">and</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">/</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">or </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">theme</span><span style="white-space:pre-wrap;"> are </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">not </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">fully </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">compatible </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">with</span><span style="white-space:pre-wrap;"> the </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">current </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">Cotonti </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">version</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">. </span>Turned off by default.</li>
	<li>Many minor improvements and fixes</li>
</ul>

<p>Read more on the <a href="https://www.cotonti.com/download/cotonti-siena-0925">release page</a>.</p>

<p>Thanks to everyone who participated in the work on this release, programming and testing</p>

<p> </p>

<p><strong>For more detailed info see:</strong></p>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.24.2...0.9.25" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/58?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.25 issues…</a></li>
</ul>
]]></description>
			<pubDate>Tue, 03 Sep 2024 06:10:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/news/announce/cotonti-siena-0925-released]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.25</title>
			<description><![CDATA[<h2>About Siena</h2>

<p>If you are a new to Cotonti — please read a brief <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">info about this CMF</a> and its <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md#requirements" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener"><strong>requirements</strong></a>.</p>

<p>See detailed <a href="https://github.com/Cotonti/Cotonti/blob/master/Install.txt" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">instructions for first-time install</a> or <a href="https://www.cotonti.com/ru/rss#ch3">updating guides</a>.</p>

<p> </p>

<h2>Release info</h2>

<p>This is a stability release that fixes bugs found after the release of 0.9.24. It is also a preparation before the 1.0 release.</p>

<h3>Whats new:</h3>

<ul>
	<li>Support for Php 5.x has been discontinued. The minimum Php version is <strong>7.3</strong></li>
	<li>Database: <strong>transactions support</strong> with nesting control</li>
	<li><code>cot_user_sqlExcludeBanned()</code> for generate sql condition to exclude banned users. You can use it your extensions.</li>
	<li><code>cot_generateCaptchaTags()</code> captcha tag generation unification for the coTemplate</li>
	<li><strong>Legacy mode</strong> (<code>$cfg['legacyMode']</code>) to turn on deprecated features. <span style="white-space:pre-wrap;">You </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">can </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">use</span><span style="white-space:pre-wrap;"> it </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">if </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">your </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">extensions </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">and</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">/</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">or </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">theme</span><span style="white-space:pre-wrap;"> are </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">not </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">fully </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">compatible </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">with</span><span style="white-space:pre-wrap;"> the </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">current </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">Cotonti </span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">version</span><span class="EzKURWReUAB5oZgtQNkl" style="white-space:pre-wrap;">. </span>Turned off by default.</li>
	<li>Many minor improvements and fixes</li>
</ul>

<h3>Template tags changes:</h3>

<p><strong>Unified captcha tags.</strong></p>

<p><strong>Unified pagination</strong> tags in pfs.admin.allpfs.tpl, polls.admin.tpl, comments.tools.tpl, ratings.admin.tpl, referers.admin.tpl, trashcan.admin.tpl:</p>

<pre class="brush:xml;">
{XXX_PAGINATION} -&gt; {PAGINATION}
{XXX_PAGEPREV} -&gt; {PREVIOUS_PAGE}
{XXX_PAGENEXT} -&gt; {NEXT_PAGE}
{XXX_TOTALITEMS} -&gt; {TOTAL_ENTRIES}
{XXX_ON_PAGE} -&gt; {ENTRIES_ON_CURRENT_PAGE}</pre>

<p> </p>

<h3>For more detailed info see:</h3>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.24.2...0.9.25" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/58?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.25 issues…</a></li>
</ul>

<p> </p>

<h2>Updating from previous versions</h2>

<ul>
	<li>For updating from previous <strong>Siena</strong> version — see instructions <a href="https://www.cotonti.com/docs/start/updating">here</a>.</li>
	<li>For upgrading from <strong>Genoa</strong> — see <a href="https://www.cotonti.com/docs/start/updating">this document</a> (you will also need files from <a href="https://github.com/Cotonti/cotonti-legacy" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">cotonti-legacy</a> to perform the upgrade).</li>
</ul>

<p> </p>

<p> </p>
]]></description>
			<pubDate>Tue, 03 Sep 2024 05:58:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/download/cotonti-siena-0925]]></link>
		</item>
		<item>
			<title>Omnis Theme</title>
			<description><![CDATA[<p dir="ltr"><img src="https://www.cotonti.com/datas/photos/page_731.jpg" alt="Omnis theme for Cotonti Siena" /></p><p dir="ltr" id="docs-internal-guid-c33be236-7fff-e535-b5c9-fd57cb4aec7f">Omnis theme was built using Bootstrap 5.3.3 and Fontawesome Free 6.5.2. Styles are written with LESS, resulting css-files are minimized. Development and testing were done using Cotonti 0.9.25 beta, all TPL-tags comply with the new naming.</p><p dir="ltr"><a target="_blank" href="https://omnis.sed.by/" rel="nofollow" rel="nofollow noreferrer noopener">Theme Demo</a></p><h2 dir="ltr">Dependencies</h2><p dir="ltr" id="docs-internal-guid-3be1f711-7fff-91fc-b1c0-09b513cb4908">In order to implement all theme features the following extensions shall be installed:</p><p dir="ltr">Official Package:</p><ul><li>Index</li><li>Page</li><li>Users</li><li>CKEditor</li><li>Comments system</li><li>Contact</li><li>HTML Parser</li><li>HTML Purifier</li><li>Math Captcha (or an alternative)</li><li>Search</li><li>Tags</li><li>User Images</li></ul><p dir="ltr">3rd party:</p><ul><li><a target="_blank" href="https://github.com/seditio/cot_archive" rel="nofollow" rel="nofollow noreferrer noopener">Archive</a></li><li><a target="_blank" href="https://github.com/seditio/cot_attach2" rel="nofollow" rel="nofollow noreferrer noopener">Attachments2</a></li><li><a target="_blank" href="https://github.com/seditio/cot_catlist" rel="nofollow" rel="nofollow noreferrer noopener">Catlist</a></li><li><a target="_blank" href="https://github.com/seditio/cot_comlist" rel="nofollow" rel="nofollow noreferrer noopener">Comlist</a></li><li><a target="_blank" href="https://github.com/seditio/cot_cotlib" rel="nofollow" rel="nofollow noreferrer noopener">Cotlib</a></li><li><a target="_blank" href="https://github.com/seditio/cot_fonts" rel="nofollow" rel="nofollow noreferrer noopener">Fonts</a> (or load Montserrat font your own way)</li><li><a target="_blank" href="https://github.com/seditio/cot_toptags" rel="nofollow" rel="nofollow noreferrer noopener">Toptags</a></li><li><a target="_blank" href="https://github.com/seditio/cot_icons" rel="nofollow" rel="nofollow noreferrer noopener">Icons</a> (todo: compile icons into a font)</li><li><a target="_blank" href="https://github.com/seditio/cot_pagelist" rel="nofollow" rel="nofollow noreferrer noopener">Pagelist</a></li><li><a target="_blank" href="https://github.com/seditio/cot_systembyalias" rel="nofollow" rel="nofollow noreferrer noopener">System pages by alias</a></li></ul><p dir="ltr" id="docs-internal-guid-28f2068e-7fff-3e70-f427-138a23eeb06a">Once the installation is complete, create a page in the <code>system</code> section with alias <code>blog</code> and title Blog. This is where all posts will be aggregated using Pagelist plugin.</p><p dir="ltr">To highlight a post in the feed create a page extrafield named special_class (type input). When editing such page use <code><tt>special</tt></code>class in the edit form to make title bolder &amp; image bigger.</p><h2 dir="ltr">How to use the theme</h2><p dir="ltr">My viewpoint can be found at the <a target="_blank" href="https://sed.by/cot/themes/omnis" rel="nofollow" rel="nofollow noreferrer noopener">Omnis officlal page</a> (Russian). Nonetheless, since in the <a target="_blank" href="https://www.cotonti.com/en/forums?m=posts&amp;q=9367&amp;n=last#bottom" rel="nofollow noreferrer noopener">recent poll</a> the majority voted for modifying ready-made themes, I see two options here:</p><h3 dir="ltr">Standard</h3><p dir="ltr">After the installation, download <a target="_blank" href="https://github.com/seditio/cot_omnis" rel="nofollow" rel="nofollow noreferrer noopener">Omnis plugin</a> and load all custom lang-strings, resources and settings (like GTM container ID). This way you can update the theme from the Github repository without fearing to overwrite some of your custom data.</p><p dir="ltr">Naturally, you are encouraged to suggest and discuss new features that will provide new functions and capabilities to the theme.</p><h3 dir="ltr">As an Intermediate Product</h3><p dir="ltr">Unpack css-files, modify LESS code, edit markup, install other plugins, and use Omnis to make your own modifications. No offense.</p><h2 dir="ltr">Todo</h2><p dir="ltr">So far it's <s>sticky header and</s> font-packed icons.</p>]]></description>
			<pubDate>Wed, 28 Aug 2024 08:00:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/themes/omnis]]></link>
		</item>
		<item>
			<title>Dark Blog</title>
			<description><![CDATA[<p>Необходимые плагины :</p>

<p><a href="https://github.com/seditio/cot_pagelist" rel="nofollow" rel="nofollow">Pagelist</a>, <a href="https://github.com/seditio/cot_catlist" rel="nofollow" rel="nofollow">Catlist</a>, <a href="https://github.com/seditio/cot_comlist" rel="nofollow" rel="nofollow">Comlist</a>, <a href="https://github.com/seditio/cot_forman" rel="nofollow" rel="nofollow">Forman</a>, <a href="https://github.com/seditio/cot_thanks" rel="nofollow" rel="nofollow">Thanks</a>, <a href="https://github.com/Kabak/cot-syntaxhighlighter" rel="nofollow" rel="nofollow">syntaxhighlighter</a>, <a href="https://github.com/Kabak/cot-attach2" rel="nofollow" rel="nofollow">attach2</a>, <a href="https://github.com/Kabak/nevalidate" rel="nofollow" rel="nofollow">nevalidate</a>, <a href="https://github.com/Kabak/toplastseen" rel="nofollow" rel="nofollow">toplastseen</a>, <a href="http://cotonti.com" rel="nofollow">Friendly functions calls</a></p>

<p>в настройках сайта</p>

<p> <img alt="" src="https://i.gyazo.com/72ed371d981e219287a7554180a1272a.png" style="width:600px;height:296px;" /></p>

<p><img alt="" src="https://i.gyazo.com/ba91aefec15e1e7ae1b47794fd5b614c.png" style="width:600px;height:256px;" /></p>

<p> </p>

<p>Меню #6<br />
{PHP.cfg.menu6} во всех файлах .tpl:    <strong><span style="color:#2ecc71;">количество выводимых на главной новых статей.</span></strong> После превышения этого числа включается паджинация</p>

<p>Чтобы страница попала в этот список нужно настроить экстрополе : </p>

<p><img alt="" src="https://i.gyazo.com/66243726c075f24597309dbd58f748a4.png" style="width:600px;height:286px;" /></p>

<p>HTML для экстрополя такой (  на картинке выше ) : </p>

<p>&lt;input type="hidden" name="{$name}" value="{$value_off}" /&gt;&lt;label&gt;&lt;input type="checkbox" name="{$name}" value="{$value}"{$checked} /&gt; {$title}&lt;/label&gt;</p>

<p> </p>

<p>После публикации статьи нужно зайти в её редактирование и установить галочку как на картинке ниже :</p>

<p><img alt="" src="https://i.gyazo.com/b7cfb3b8f72d06be2c2141909e33e926.png" style="width:600px;height:291px;" /></p>

<p> </p>

<p>Меню #7<br />
{PHP.cfg.menu7} во всех файлах .tpl: <span style="color:#2ecc71;"><strong>количество последних сообщений с форуса</strong></span></p>

<p> </p>

<p>Меню #8<br />
{PHP.cfg.menu8} во всех файлах .tpl: <strong><span style="color:#1abc9c;">количество отображаемых последних статей</span></strong></p>

<p> </p>

<p>Меню #9<br />
{PHP.cfg.menu9} во всех файлах .tpl: <strong><span style="color:#1abc9c;">оличество отображаемых последних комментариев </span></strong></p>

<p> </p>

<p>Как выглядит  -&gt;  <a href="http://93.125.49.123/blog/index.php" rel="nofollow" rel="nofollow">здесь</a></p>
]]></description>
			<pubDate>Tue, 20 Aug 2024 20:17:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/themes/dark-blog]]></link>
		</item>
		<item>
			<title>Using Composer</title>
			<description><![CDATA[<div><img alt="" src="https://www.cotonti.com/datas/users/composer_0.png" /></div>

<p>Cotonti Siena 0.9.23 features <a href="https://getcomposer.org/" rel="nofollow" rel="nofollow">Composer</a> support. Composer is a tool for dependency management in PHP.</p>

<h2>What is Composer</h2>

<p dir="ltr" id="docs-internal-guid-a24f240e-7fff-6727-541a-b7c419e10575" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong>Composer is a dependency manager </strong>designed to simplify uploading and using 3rd party PHP libraries in your project. In instance, it can be used to add all necessary libs into an extension that is being developed.</p>

<p dir="ltr"><strong>composer.json </strong>is a text file where all side libs (packages) the project is based on are defined. Additionally it contains data on project info, PHP minimum version and required PHP extensions.</p>

<p dir="ltr"><strong>composer.lock </strong>contains a current list of all installed dependencies and their versions. The main purpose of this file is to save the complete environment in which the project is being developed and tested.</p>

<p dir="ltr">For example, if you work in a team you have to make sure that your colleague having downloaded (pull) the project from a git repository will receive the same environment and package versions that you use.</p>

<p dir="ltr">When a project is deployed to the live environment you have to make sure that it uses the same versions as in the development environment. This ensures that any location your project is deployed in is identical to the one used in the development and helps eliminate errors that might occur due to the versions updates.</p>

<h2>Using Composer to Develop Extensions</h2>

<p dir="ltr" id="docs-internal-guid-67285126-7fff-7ba4-6874-7e492936cf97" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;">First off, make sure that <a href="https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos" rel="nofollow" rel="nofollow">Composer is installed</a>.</p>

<p dir="ltr">Next we will add the <a href="https://docs.guzzlephp.org" rel="nofollow" rel="nofollow">Guzzle </a>client to a Cotonti extension. This ensures that both sync and async requests are sent to remote servers using the same interface. A great tool for integration with various APIs.</p>

<p dir="ltr">We will also use <a href="https://flysystem.thephpleague.com" rel="nofollow" rel="nofollow">Flysystem </a>to upload files into a remote storage.</p>

<p dir="ltr">These two are used only as an example with no connection between them.</p>

<p dir="ltr">Let’s begin.</p>

<p dir="ltr">We follow <a href="https://docs.guzzlephp.org/en/stable/overview.html#installation" rel="nofollow" rel="nofollow">Guzzle installation manual</a> to add section <code>require </code>into the file composer.json located in the project root:</p>

<pre class="brush:plain;">
"guzzlehttp/guzzle": "^7.8"</pre>

<p>This would result in something like this:</p>

<pre class="brush:plain;">
"require": {
    "php": "&gt;=5.6",
    "ext-gd": "*",
    "ext-mbstring": "*",
    "ext-json": "*",
    "ext-hash": "*",
    "ext-pdo": "*",
    "guzzlehttp/guzzle": "^7.8"
},</pre>

<p><span id="docs-internal-guid-85c4fa50-7fff-2520-120b-4615266af32a" style="font-size:11pt;font-family:Arial, sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">Next we execute the following code in the command line:</span></p>

<pre class="brush:bash;">
&gt; composer update</pre>

<p dir="ltr" id="docs-internal-guid-9bf66403-7fff-622d-cea4-2595ac74ce9b" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;">This command updates all dependencies installed within the project to the latest version available (as per <strong>composer.json</strong>), installs new dependencies added to <strong>composer.json</strong> and removes those that no longer exist. Following that Composer updates <strong>composer.lock</strong>.</p>

<p dir="ltr">Now our HTTP client is ready for use.</p>

<p dir="ltr">Next we add the following code to our extension:</p>

<pre class="brush:php;">
&lt;?php

use GuzzleHttp\Client;

// Create client instance with base URI
$client = new Client(['base_uri' =&gt; 'https://foo.com/api/']);

// Send POST-request application/x-www-form-urlencoded to https://foo.com/api/test
$response = $client-&gt;request('POST', '/test', [
  'form_params' =&gt; [
      'field_name' =&gt; 'abc',
      'other_field' =&gt; '123',
      'nested_field' =&gt; [
          'nested' =&gt; 'hello',
      ],
  ],
]);

$body = $response-&gt;getBody();
echo $body;</pre>

<p dir="ltr" id="docs-internal-guid-c019e31a-7fff-2749-62f9-505bbe46ce69" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;">Dead easy, is it?</p>

<p dir="ltr">Now we proceed to remote uploads.</p>

<p dir="ltr">As specified in the <a href="https://flysystem.thephpleague.com/docs/getting-started/" rel="nofollow" rel="nofollow">documentation </a>we add section <code>require </code>to composer.json:</p>

<pre class="brush:plain;">
"league/flysystem": "^3.0",
"league/flysystem-aws-s3-v3": "^3.0"</pre>

<p>Over again:</p>

<pre class="brush:bash;">
&gt; composer update</pre>

<p>Everything set. We can now use the library in our extension.</p>

<pre class="brush:php;">
&lt;?php

use Aws\S3\S3Client;
use League\Flysystem\AwsS3V3\AwsS3V3Adapter;
use League\Flysystem\Filesystem;

// For some reason AWS adapter works this way only
putenv('AWS_ACCESS_KEY_ID=my-access-key');
putenv('AWS_SECRET_ACCESS_KEY=my-secret-key');

/** @var S3ClientInterface $client */
$client = new S3Client([
    'version' =&gt; 'latest',
    'endpoint' =&gt; 'https://storage.yandexcloud.net',
    'region' =&gt; 'ru-central1',
]);

// The internal adapter
$adapter = new AwsS3V3Adapter(
    $client, // S3Client
    'test-new-bucket', // Bucket name
    'path/to/upload/dir' // path prefix
);


// FilesystemOperator готов и сконфигурирован. Можно использовать.
$fileSystem = new Filesystem($adapter);

// Запись в файл
$filesystem-&gt;write($path, $contents);</pre>

<p>That is all. Do not forget to specify in the extension installation manual instruction to add the following lines to <strong>composer.json</strong> and run <strong>composer update</strong>:</p>

<pre class="brush:plain;">
"guzzlehttp/guzzle": "^7.8",
"league/flysystem": "^3.0",
"league/flysystem-aws-s3-v3": "^3.0"</pre>

<h2>Deploy Project into the Live Server</h2>

<p dir="ltr" id="docs-internal-guid-5c36e462-7fff-f056-412a-35de985557fa" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;">Our project is ready and is git-managed. Time to move it to the production server.</p>

<p dir="ltr">In the <strong>lib/vendor </strong>folder we got new subfolders with dependencies added by Composer. Let’s add them into the <code>.gitignore</code> – no need to use them in the repository and increase its size.</p>

<p dir="ltr">Now commit the changes and push them into the repository.</p>

<p dir="ltr">Next we login into the server via SSH and execute:</p>

<pre class="brush:bash;">
&gt; git pull</pre>

<p>Followed by:</p>

<pre class="brush:bash;">
&gt; composer install</pre>

<p dir="ltr" id="docs-internal-guid-605b65fa-7fff-14fe-4465-e0acc487cbcb" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;">Unlike <code>composer update</code> this command shall install all dependencies listed in <strong>composer.lock </strong>and only the versions specified there. If this file is missing in the project root, this command shall act similar to <code>composer update</code> and use <strong>composer.json </strong>to install dependencies.</p>

<p dir="ltr">We’re done. You can now open the project in the browser and enjoy the result.</p>
]]></description>
			<pubDate>Fri, 24 May 2024 10:32:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/docs/ext/using-composer]]></link>
		</item>
		<item>
			<title>Project to Expire</title>
			<description><![CDATA[<p>The time to project expiration is a string in the "2 days 18:10:45" format. The order and divider can be customized via resource string located in the inc/pte.rc.php</p>

<h2>TPL-tags</h2>

<p>projects.list.tpt:</p>

<pre class="brush:xml;">
...
&lt;!-- BEGIN: PRJ_ROWS  --&gt;
...
Project expires in: {PRJ_ROW_PTE_TO_EXPIRE}
...
&lt;!-- END: PRJ_ROWS  --&gt;
...</pre>

<p>projects.tpl:</p>

<pre class="brush:xml;">
{PRJ_PTE_TO_EXPIRE}</pre>
]]></description>
			<pubDate>Fri, 26 Apr 2024 05:56:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/project-to-expire]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.24.2 released</title>
			<description><![CDATA[<p><strong>Whats new:</strong></p>

<ul>
	<li><strong>СoTemplate</strong>. Support for multiple function arguments. Now you can use other tags as function arguments. You can write like this:

	<pre class="brush:xml;">
{PHP|cot_url('page', 'c=news')|var_dump({PHP.L.Home}, $this, {PHP.cfg.mainurl}, {PHP|cot_url('page', 'c=news ')}, {HEADER_TITLE})}</pre>
	The <code>$this</code> support is left in place. You can still use function call chains.</li>
	<li><strong>СoTemplate</strong>. Strict comparison operators: <code>===</code> and <code>!==</code></li>
	<li>Fixed a bug where data from the database cache might not be loaded automatically.</li>
	<li><strong>Static cache</strong> improvements.</li>
	<li>You can now use comments in <strong>Url editor</strong>'s *.dat files</li>
	<li><strong>Forums</strong> API. A new function <code>cot_forums_sqlExcludePrivateTopics()</code> that generates an SQL condition to exclude private topics from the selection, based on the the current user's rights. You can use it in your extensions.</li>
	<li>The <strong>page</strong> views counter now works even when the static page cache is enabled.</li>
	<li><strong>Captcha</strong> and posting <strong>comments</strong> by guests now work when static page cache is enabled.</li>
	<li><strong>Search</strong>. The default sorting is by date descending.</li>
	<li>Fixed/added meta tags title, description and canonical url in some extensions</li>
	<li>Function <code>cot_generatePaginationTags()</code> for uniform generation of pagination tags in extensions.</li>
	<li><strong>Extrafields</strong>. Field name validation.</li>
	<li><strong>CKEditor</strong> has been updated to version 4.22.1. In future releases, it will be replaced with version 5.</li>
	<li>Refactoring of tags in templates has begun. Making tags more understandable and convenient. The old tags are kept for backward compatibility, but will be removed in the future. We recommend updating your themes.</li>
	<li>The Composer folder has been moved to lib/vendor</li>
	<li>1st part of <strong>Tags</strong> plugin improvements</li>
	<li>Improvements to the <strong>Recent items</strong> plugin</li>
	<li>Other minor improvements</li>
	<li>Fix for various errors found during operation.</li>
</ul>

<p>Read more on the <a href="https://www.cotonti.com/download/cotonti-siena-0924">release page</a>.</p>

<p>Thanks to everyone who participated in the work on this release, programming and testing</p>

<p> </p>

<p><strong>For more detailed info see:</strong></p>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.23...0.9.24.2" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/57?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.24 issues…</a></li>
</ul>
]]></description>
			<pubDate>Fri, 02 Feb 2024 12:43:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/news/announce/cotonti-siena-0924-released]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.24.2</title>
			<description><![CDATA[<h2>About Siena</h2>

<p>If you are a new to Cotonti — please read a brief <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">info about this CMF</a> and its <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md#requirements" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener"><strong>requirements</strong></a>.</p>

<p>See detailed <a href="https://github.com/Cotonti/Cotonti/blob/master/Install.txt" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">instructions for first-time install</a> or <a href="https://www.cotonti.com/ru/rss#ch3">updating guides</a>.</p>

<p> </p>

<h2>Release info</h2>

<h3>Whats new:</h3>

<ul>
	<li><strong>СoTemplate</strong>. Support for multiple function arguments. Now you can use other tags as function arguments. You can write like this:

	<pre class="brush:xml;">
{PHP|cot_url('page', 'c=news')|var_dump({PHP.L.Home}, $this, {PHP.cfg.mainurl}, {PHP|cot_url('page', 'c=news ')}, {HEADER_TITLE})}</pre>
	The <code>$this</code> support is left in place. You can still use function call chains.</li>
	<li><strong>СoTemplate</strong>. Strict comparison operators: <code>===</code> and <code>!==</code></li>
	<li>Fixed a bug where data from the database cache might not be loaded automatically.</li>
	<li><strong>Static cache</strong> improvements.</li>
	<li>You can now use comments in <strong>Url editor</strong>'s *.dat files</li>
	<li><strong>Forums</strong> API. A new function <code>cot_forums_sqlExcludePrivateTopics()</code> that generates an SQL condition to exclude private topics from the selection, based on the the current user's rights. You can use it in your extensions.</li>
	<li>The <strong>page</strong> views counter now works even when the static page cache is enabled.</li>
	<li><strong>Captcha</strong> and posting <strong>comments</strong> by guests now work when static page cache is enabled.</li>
	<li><strong>Search</strong>. The default sorting is by date descending.</li>
	<li>Fixed/added meta tags title, description and canonical url in some extensions</li>
	<li>Function <code>cot_generatePaginationTags()</code> for uniform generation of pagination tags in extensions.</li>
	<li><strong>Extrafields</strong>. Field name validation.</li>
	<li><strong>CKEditor</strong> has been updated to version 4.22.1. In future releases, it will be replaced with version 5.</li>
	<li>Refactoring of tags in templates has begun. Making tags more understandable and convenient. The old tags are kept for backward compatibility, but will be removed in the future. We recommend updating your themes.</li>
	<li>The Composer folder has been moved to lib/vendor</li>
	<li>1st part of <strong>Tags</strong> plugin improvements</li>
	<li>Improvements to the <strong>Recent items</strong> plugin</li>
	<li>New setting in <strong>config.php</strong>: <code>$cfg['legacyMode']</code>. If <code>false</code>, it disables all deprecated functionality.</li>
	<li>Other minor improvements</li>
	<li>Fix for various errors found during operation.</li>
</ul>

<p> </p>

<h3>Template tags changes:</h3>

<p><strong>Unified captcha tags:</strong></p>

<p><strong>users.register.tpl</strong><br />
{USERS_REGISTER_VERIFYIMG} -&gt; {USERS_REGISTER_VERIFY_IMG}<br />
{USERS_REGISTER_VERIFYINPUT} -&gt; {USERS_REGISTER_VERIFY_INPUT}</p>

<p><strong>comments.tpl</strong><br />
{COMMENTS_FORM_VERIFYIMG} -&gt; {COMMENTS_FORM_VERIFY_IMG}<br />
{COMMENTS_FORM_VERIFY} -&gt; {COMMENTS_FORM_VERIFY_INPUT}</p>

<p><strong>contact.tpl</strong><br />
{CONTACT_FORM_VERIFY} -&gt; {CONTACT_FORM_VERIFY_INPUT}</p>

<p> </p>

<p><strong>Unified pagination tags:</strong><br />
{&lt;prefix&gt;PAGINATION}<br />
{&lt;prefix&gt;PREVIOUS_PAGE}<br />
{&lt;prefix&gt;NEXT_PAGE}<br />
{&lt;prefix&gt;CURRENT_PAGE}<br />
{&lt;prefix&gt;TOTAL_ENTRIES}<br />
{&lt;prefix&gt;ENTRIES_ON_CURRENT_PAGE}<br />
{&lt;prefix&gt;ENTRIES_PER_PAGE}<br />
{&lt;prefix&gt;TOTAL_PAGES}</p>

<p>&lt;prefix&gt; can be empty. Or not, if there are more than one paginations on the page.<br />
For example on page.list.tpl:</p>

<p>{LIST_CAT_PAGINATION} for categories list and {PAGINATION} for pages list.</p>

<p><br />
<strong>forums.posts.tpl</strong><br />
{FORUMS_POSTS_BREADCRUMBS} - new<br />
{FORUMS_POSTS_SHORTTITLE} -&gt; {FORUMS_POSTS_TITLE}<br />
{FORUMS_POSTS_PAGETITLE} -&gt; {PAGEEDIT_FORM_DESCRIPTION}</p>

<p><br />
all user tags tags: {FORUMS_POSTS_ROW_USERXXX} -&gt; {FORUMS_POSTS_ROW_USER_XXX}<br />
e.g.<br />
{FORUMS_POSTS_ROW_USERNAME} -&gt; {FORUMS_POSTS_ROW_USER_NAME}<br />
{FORUMS_POSTS_ROW_USERAVATAR} -&gt; {FORUMS_POSTS_ROW_USER_AVATAR}<br />
etc.</p>

<p>{PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE} and other pagination tags without prefix</p>

<p> </p>

<p><strong>polls.admin.tpl</strong><br />
{ADMIN_POLLS_ROW_POLL_URL_DEL} deprecated<br />
{ADMIN_POLLS_ROW_POLL_DELETE_URL} - new<br />
{ADMIN_POLLS_ROW_POLL_DELETE_CONFIRM_URL} - new</p>

<p> </p>

<p><strong>system/admin/tpl/admin.extensions.tpl</strong><br />
{ADMIN_EXTENSIONS_DETAILS_ROW_ORDER_INSTALLED}<br />
{ADMIN_EXTENSIONS_DETAILS_ROW_HOOKS_INSTALLED}</p>

<p> </p>

<p><strong>page.list.tpl (same changes in cot_page_enum())</strong><br />
{LIST_CATTITLE} -&gt; {LIST_BREADCRUMBS} - new<br />
{LIST_BREADCRUMBS_SHORT} - new<br />
{LIST_ROWCAT_URL} -&gt; {LIST_CAT_ROW_URL}<br />
{LIST_ROWCAT_TITLE} -&gt; {LIST_CAT_ROW_TITLE}<br />
{LIST_ROWCAT_COUNT} -&gt; {LIST_CAT_ROW_COUNT}<br />
{LIST_ROWCAT_DESC} -&gt; {LIST_CAT_ROW_DESCRIPTION}</p>

<p>{LIST_CAT_XXX} - pagination for categories with prefix 'LIST_CAT_', e.g. {LIST_CAT_PREVIOUS_PAGE}, {LIST_CAT_PAGINATION}<br />
And without prefix for pages list e.g. {PREVIOUS_PAGE}, {PAGINATION}.</p>

<p>Block LIST_ROWCAT -&gt; LIST_CAT_ROW</p>

<p>{LIST_ROW_XXX} - page tags see below.</p>

<p><br />
<strong>page.tpl, page.enum.tpl (from cot_generate_pagetags())</strong><br />
{PAGE_TITLE} now contains exactly the title, not the breadcrumbs<br />
{PAGE_BREADCRUMBS} - new<br />
{PAGE_LOCALSTATUS} -&gt; {PAGE_LOCAL_STATUS}<br />
{PAGE_SHORTTITLE} - deprecated<br />
{PAGE_CATURL} -&gt; {PAGE_CAT_URL}<br />
{PAGE_CATTITLE} -&gt; {PAGE_CAT_TITLE}<br />
{PAGE_CATPATH} -&gt; {PAGE_CAT_PATH}<br />
{PAGE_CATPATH_SHORT} -&gt; {PAGE_CAT_PATH_SHORT}<br />
{PAGE_CATDESC} -&gt; {PAGE_CAT_DESCRIPTION}<br />
{PAGE_CATICON} -&gt; {PAGE_CAT_ICON}<br />
{PAGE_CAT_ICON_SRC} - new<br />
{PAGE_DESC} -&gt; {PAGE_DESCRIPTION}<br />
{PAGE_DESC_OR_TEXT} -&gt; {PAGE_DESCRIPTION_OR_TEXT}<br />
{PAGE_DESC_OR_TEXT_CUT} -&gt; {PAGE_DESCRIPTION_OR_TEXT_CUT}<br />
{PAGE_OWNERID} -&gt; {PAGE_OWNER_ID}<br />
{PAGE_OWNERNAME} -&gt; {PAGE_OWNER_NAME}<br />
{PAGE_DATE} -&gt; {PAGE_CREATED}<br />
{PAGE_DATE_STAMP} -&gt; {PAGE_CREATED_STAMP}<br />
{PAGE_FILE_COUNT} -&gt; {PAGE_FILE_DOWNLOADS}<br />
{PAGE_FILE_COUNTTIMES} -&gt; {PAGE_FILE_DOWNLOADS_TIMES}<br />
{PAGE_COUNT} -&gt; {PAGE_HITS}<br />
{PAGE_NOTAVAILABLE} -&gt; {PAGE_NOT_AVAILABLE}</p>

<p><br />
<strong>page.add.tpl</strong><br />
{PAGEADD_FORM_DESC} -&gt; {PAGEADD_FORM_DESCRIPTION}<br />
{PAGEADD_FORM_OWNERID} -&gt; {PAGEADD_FORM_OWNER_ID}</p>

<p> </p>

<p><strong>page.edit.tpl</strong><br />
{PAGEEDIT_FORM_LOCALSTATUS} -&gt; {PAGEEDIT_FORM_LOCAL_STATUS}<br />
{PAGEEDIT_FORM_DESC} -&gt; {PAGEEDIT_FORM_DESCRIPTION}<br />
{PAGEEDIT_FORM_OWNERID} -&gt; {PAGEEDIT_FORM_OWNER_ID}<br />
{PAGEEDIT_FORM_PAGECOUNT} -&gt; {PAGEEDIT_FORM_HITS}<br />
{PAGEEDIT_FORM_FILECOUNT} -&gt; {PAGEEDIT_FORM_FILE_DOWNLOADS}</p>

<p><br />
<strong>pm.list.tpl, pm.message.tpl</strong><br />
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...</p>

<p> </p>

<p><strong>polls.admin.tpl</strong><br />
{ADMIN_POLLS_ROW_POLL_DELETE_CONFIRM_URL} - new<br />
{ADMIN_POLLS_ROW_POLL_URL_DEL} -&gt; {ADMIN_POLLS_ROW_POLL_DELETE_URL}</p>

<p><br />
<strong>users.edit.php</strong><br />
{USERS_EDIT_TITLE} - now it is a page title<br />
{USERS_EDIT_BREADCRUMBS} - new<br />
{USERS_EDIT_DETAILSLINK} -&gt; {USERS_EDIT_DETAILS_URL}<br />
{USERS_EDIT_MAINGRP} -&gt; {USERS_EDIT_MAIN_GROUP}</p>

<p> </p>

<p><strong>users.passrecover.tpl</strong><br />
{PASSRECOVER_TITLE} - now it is a page title<br />
{PASSRECOVER_BREADCRUMBS} - new</p>

<p> </p>

<p><strong>users.profile.tpl</strong><br />
{USERS_PROFILE_TITLE} - now it is a page title<br />
{USERS_PROFILE_BREADCRUMBS} - new<br />
{USERS_PROFILE_DETAILSLINK} -&gt; {USERS_PROFILE_DETAILS_URL}<br />
{USERS_PROFILE_EDITLINK} -&gt; {USERS_PROFILE_EDIT_URL}</p>

<p> </p>

<p><strong>users.tpl</strong><br />
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...<br />
{USERS_TOP_USERID} -&gt; {USERS_TOP_USER_ID}<br />
{USERS_TOP_MAINGRP} -&gt; {USERS_TOP_MAIN_GROUP}<br />
{USERS_TOP_REGDATE} -&gt; {USERS_TOP_REGISTRATION_DATE}<br />
{USERS_TOP_LOGCOUNT} -&gt; {USERS_TOP_LOGINS_COUNT}<br />
{USERS_TOP_GRPLEVEL} -&gt; {USERS_TOP_GROUP_LEVEL}<br />
{USERS_TOP_GRPTITLE} -&gt; {USERS_TOP_GROUP_TITLE}<br />
{USERS_TOP_POSTCOUNT} -&gt; {USERS_TOP_POSTS_COUNT}<br />
{USERS_TITLE} - now it is a page title<br />
{USERS_BREADCRUMBS} - new<br />
{USERS_TOP_FILTER_ACTION} -&gt; {USERS_FILTERS_ACTION}<br />
{USERS_FILTERS_PARAMS} - new<br />
{USERS_TOP_FILTERS_COUNTRY} -&gt; {USERS_FILTERS_COUNTRY}<br />
{USERS_TOP_FILTERS_MAINGROUP} -&gt; {USERS_FILTERS_MAIN_GROUP}<br />
{USERS_TOP_FILTERS_GROUP} -&gt; {USERS_FILTERS_GROUP}<br />
{USERS_TOP_FILTERS_SEARCH} -&gt; {USERS_FILTERS_SEARCH}<br />
{USERS_TOP_FILTERS_SUBMIT} -&gt; {USERS_FILTERS_SUBMIT}<br />
{USERS_FILTERS_SORT}<br />
{USERS_FILTERS_SORT_WAY_URL}<br />
{USERS_FILTERS_SORT_WAY}</p>

<p><br />
<strong>recentitems.tpl</strong><br />
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...</p>

<p> </p>

<p><strong>recentitems.forums.index.tpl, recentitems.forums.tpl</strong><br />
{FORUM_ROW_FIRSTPOSTER} -&gt; {FORUM_ROW_FIRST_POSTER}<br />
{FORUM_ROW_LASTPOSTER} -&gt; {FORUM_ROW_LAST_POSTER}<br />
{FORUM_ROW_TIMEAGO} -&gt; {FORUM_ROW_TIME_AGO}<br />
{FORUM_ROW_POSTCOUNT} -&gt; {FORUM_ROW_POSTS_COUNT}<br />
{FORUM_ROW_CREATIONDATE} -&gt; {FORUM_ROW_CREATED}<br />
{FORUM_ROW_CREATIONDATE_STAMP} -&gt; {FORUM_ROW_CREATED_STAMP}<br />
{FORUM_ROW_REPLYCOUNT} -&gt; {FORUM_ROW_REPLY_COUNT}<br />
{FORUM_ROW_VIEWCOUNT} -&gt; {FORUM_ROW_VIEWS_COUNT}<br />
{FORUM_ROW_LASTPOSTURL} -&gt; {FORUM_ROW_LAST_POST_URL}<br />
{FORUM_ROW_MAXPAGES} -&gt; {FORUM_ROW_MAX_PAGES}<br />
{FORUM_ROW_DESC} -&gt; {FORUM_ROW_DESCRIPTION}</p>

<p>First poster user tags: {FORUM_ROW_FIRST_POSTER_XXX}<br />
Last poster user tags: {FORUM_ROW_LAST_POSTER_XXX}</p>

<p><br />
<strong>recentitems.pages.tpl, recentitems.pages.index.tpl, search.tpl</strong><br />
see page.tpl (from cot_generate_pagetags())</p>

<p><br />
<strong>tags.tpl</strong><br />
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...</p>

<p>If you are not sure about the tag you need, you can use the Nemesis theme as a sample or look into the extension code that you need.<br />
Also you can see a <a href="https://www.cotonti.com/docs/ext/themes/cotemplate_debug_mode">list of available tags and blocks on of the current template</a></p>

<p> </p>

<h3>For more detailed info see:</h3>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.23...0.9.24.2" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/57?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.24 issues…</a></li>
</ul>

<p> </p>

<h2>Updating from previous versions</h2>

<ul>
	<li>For updating from previous <strong>Siena</strong> version — see instructions <a href="https://www.cotonti.com/docs/start/updating">here</a>.</li>
	<li>For upgrading from <strong>Genoa</strong> — see <a href="https://www.cotonti.com/docs/start/updating">this document</a> (you will also need files from <a href="https://github.com/Cotonti/cotonti-legacy" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">cotonti-legacy</a> to perform the upgrade).</li>
</ul>

<p> </p>

<p> </p>
]]></description>
			<pubDate>Sun, 28 Jan 2024 15:07:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/download/cotonti-siena-0924]]></link>
		</item>
		<item>
			<title>Editor.js</title>
			<description><![CDATA[<p>Удобный, современный блочный редактор контента на основе <a href="https://editorjs.io/" rel="nofollow">Editor.js</a>.</p>

<p>Github плагина: <a href="https://github.com/Edd-G/cot-editorjs" rel="nofollow">https://github.com/Edd-G/cot-editorjs</a></p>

<h2>Что означает "блочный редактор"?</h2>

<p>В отличие от классических редакторов, рабочее пространство которых состоит из одного редактируемого элемента, в блочном редакторе рабочее пространство состоит из отдельных блоков: абзацев, заголовков, изображений, галерей, списков, цитат и т. д.</p>

<p>В чем преимущества перед классическими?</p>

<ol>
	<li>На выходе макисмально чистый и предсказуемый код: без лишних переносов строк, заполнителей, параграфов и т.д.</li>
	<li>Пользователь максимально сконцетрирован на созднии контента, точно зная, как это будет выглядеть на выходе.</li>
	<li>Есть десятки готовых к использованию блоков и простой API для создания любого блока, который вам нужен. Например, вы можете реализовать блоки для твитов, постов в Instagram, опросов, анкет и т. д.</li>
</ol>

<h2>Пример редактора</h2>

<p> </p>

<p><img alt="" src="https://www.cotonti.com/datas/users/editor-example_1197.jpg" style="max-width:500px;" /></p>

<h2> </h2>

<h2>Особенности этого плагина</h2>

<ol>
	<li>В оригинале Editor.js на выходе дает JSON-объект с данными каждого блока. Этот плагин, по крайней мере в текущей версии, конвертирует JSON в чистый HTML, промаркированный специальными классами. <strong>Данные в базе хранятся именно в HTML.</strong><br />
	Я сделал это для обратной совместимости с другими редакторами, если вам вдруг вздумается переключиться на классический редактор, вы сможете легко это сделать.</li>
	<li>Плагин пока поддерживает только модуль Pages. И только 1 экземпляр редактора на странице.</li>
	<li>Плагин размечает создаваемые HTML блоки специальными классами. Если у вас уже есть контент, и вы установите данный редактор, то парсер не найдет нужных CSS классов для рабора.<br />
	В этом случае Editor.js сам попробует разобрать HTML. В большинстве случаев это будет довольно криво.</li>
	<li>Загрузка изображений работает пока только с помощью <a href="https://github.com/editor-js/simple-image" rel="nofollow">@editorjs/simple-image</a>. Это значит, что добавить картинку получится только бросив ссылку на нее в редактор. Конечно можно кидать ссылки локального сервера.</li>
	<li>В текущей версии не реализована загрузка файлов. По крайней мере пока не сделали API какого-то файлового менеджера.</li>
	<li>Существует проблема с предпросмотром некотрых ссылок в <a href="https://github.com/editor-js/link" rel="nofollow">@editorjs/link</a>. Это связано с тем, что ресурс по ссылке под защитой какого-то сервиса, вроде Cloudflare. </li>
</ol>

<h2>Поддерживаемые блоки Editor.js</h2>

<ul>
	<li><a href="https://github.com/editor-js/paragraph" rel="nofollow">Paragraph</a></li>
	<li><a href="http://github.com/kaaaaaaaaaaai/paragraph-with-alignment" rel="nofollow">Paragraph-with-alignment</a></li>
	<li><a href="https://github.com/editor-js/header" rel="nofollow">Header</a></li>
	<li><a href="https://github.com/wandersonsousa/header-with-alignment" rel="nofollow">Header-with-alignment</a></li>
	<li><a href="https://github.com/editor-js/list" rel="nofollow">List (ul, ol)</a></li>
	<li><a href="https://github.com/editor-js/link" rel="nofollow">Link (Opengraph)</a></li>
	<li><a href="https://github.com/editor-js/table" rel="nofollow">Table</a></li>
	<li><a href="https://github.com/editor-js/code" rel="nofollow">Code</a></li>
	<li><a href="https://github.com/editor-js/raw" rel="nofollow">Raw</a></li>
	<li><a href="https://github.com/editor-js/embed" rel="nofollow">Embed</a> (проверен только Youtube)</li>
	<li><a href="https://github.com/editor-js/delimiter" rel="nofollow">Delimiter</a></li>
	<li><a href="https://github.com/editor-js/inline-code" rel="nofollow">Inline code</a></li>
	<li><a href="https://github.com/editor-js/marker" rel="nofollow">Marker</a></li>
	<li><a href="https://github.com/editor-js/underline" rel="nofollow">Underline</a></li>
	<li><a href="https://github.com/vishaltelangre/editorjs-alert" rel="nofollow">Alert</a></li>
	<li><a href="https://github.com/editor-js/warning" rel="nofollow">Warning</a></li>
	<li><a href="https://github.com/editor-js/quote" rel="nofollow">Quote</a></li>
</ul>

<p>Подробнее о поддерживаемых блоках на <a href="https://github.com/Edd-G/cot-editorjs" rel="nofollow">Github</a>.</p>

<h2>Генерируемый плагином HTML</h2>

<h3>Header</h3>

<pre class="brush:as3;">
&lt;h2 class="prs-header prs_center"&gt;Lorem&lt;/h2&gt;</pre>

<h3>Paragraph</h3>

<pre class="brush:as3;">
&lt;p class="prs-paragraph prs_center"&gt;
    &lt;code class="inline-code"&gt;Pellentesque&lt;/code&gt; 
    &lt;i&gt;malesuada fames&lt;/i&gt; 
    &lt;mark class="cdx-marker"&gt;tempus&lt;/mark&gt;
&lt;/p&gt;</pre>

<h3>Ordered List</h3>

<pre class="brush:as3;">
&lt;ol class="prs-list prs_ordered"&gt;
    &lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;</pre>

<h3>Table</h3>

<pre class="brush:as3;">
&lt;table class="prs-table prs_withheadings"&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;1&lt;/th&gt;&lt;th&gt;2&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;a&lt;/td&gt;&lt;td&gt;b&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;</pre>

<p>Остальные примеры на <a href="https://github.com/Edd-G/cot-editorjs?tab=readme-ov-file#generated-html" rel="nofollow">Github</a></p>

<h2>Установка плагина</h2>

<ol>
	<li>Распакуйте в каталог плагинов</li>
	<li>Включите плагин в панели администратора</li>
	<li>Этот шаг нужен, если качали плагин в виде исходного кода с Github: запустите <code>composer install</code> внутри папки <code>src</code> в директории плагина (Composer должен быть установлен)</li>
	<li>Установите парсер разметки Editorjs в модуле конфигурации Страниц (модуль Pages)</li>
</ol>

<h2>Настройки</h2>

<ol>
	<li>Вы можете отключить ненужные блоки Editor.js в файле editorjs.editor.php</li>
	<li>Плагин использует свою копию HTMLpurifier. Настройте очистку данных приходящих с фронтенда с помощью правил HTML Purifier в файле <code>sanitize-blocks-config.json </code><a href="https://github.com/editor-js/editorjs-php" rel="nofollow">Подробнее о правилах в этом файле</a></li>
	<li>Префикс CSS классов (по умолчанию prs) меняется в конфигурации плагина</li>
</ol>

<h2>В планах</h2>

<ul>
	<li>Добавить выбор варианта хранения данных в базе: JSON/HTML</li>
	<li>Добавить блоки для работы с изображениями и файлами</li>
</ul>
]]></description>
			<pubDate>Sun, 07 Jan 2024 10:53:27 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/editor-parser/editorjs]]></link>
		</item>
		<item>
			<title>Nomerge</title>
			<description><![CDATA[<p>This simple plugin lets you define forum topics where posts will not be merged. Use plugin config to specify topics number, comma-separated.</p>
]]></description>
			<pubDate>Thu, 30 Nov 2023 17:09:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/nomerge]]></link>
		</item>
		<item>
			<title>Syntax Highlighter</title>
			<description><![CDATA[<p>Client side code highlighter. This is ready-to-use Cotonti port of <a href="https://github.com/syntaxhighlighter/syntaxhighlighter" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">SyntaxHighlighter</a> by Alex Gorbatchev.</p>

<p>Authors:</p>

<ul>
	<li>SyntaxHighlighter: <a href="https://github.com/alexgorbatchev" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Alex Gorbatchev</a></li>
	<li>Cotonti plugin: <a href="https://github.com/trustmaster" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Vladimir Sibirov</a> (<a href="https://www.cotonti.com/users/Trustmaster" rel="nofollow">Trustmaster</a>)</li>
	<li>Cotonti plugin: <a href="https://github.com/Alex300" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Alexey Kalnov</a> (<a href="https://www.cotonti.com/users/Alex300" rel="nofollow">Alex300</a>)</li>
	<li>Cotonti color theme: <a href="https://github.com/macik" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Andrey Matsovkin</a>, (<a href="https://www.cotonti.com/users/Macik" rel="nofollow">Macik</a>)</li>
</ul>

<p>GitHub: <a href="https://github.com/Cotonti-Extensions/syntax-highlighter" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Cotonti-Extensions/syntax-highlighter</a></p>

<p> </p>

<h2>Installation</h2>

<ul>
	<li>Download the plugin and extract "<strong>syntaxhighlighter</strong>" folder into your Cotonti plugins folder.</li>
	<li>Go to Administration / Extensions and install the <strong>SyntaxHighlighter</strong> plugin.</li>
	<li>Go to the plugin configuration and select the desired theme and set other options if you need</li>
</ul>

<p> </p>

<h2>Usage</h2>

<p>Usage with HTML parsing: To highlight source code with some specific language, use HTML tags like this:</p>

<pre class="brush:xml;">
&lt;pre class="brush:language;"&gt;
    Your code here
&lt;/pre&gt;</pre>

<p> </p>

<p>The list of available brushes and themes: <a href="https://github.com/syntaxhighlighter/syntaxhighlighter/wiki/Brushes-and-Themes" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/syntaxhighlighter/syntaxhighlighter/wiki/Brushes-and-Themes</a></p>

<p>Plugin for CKEditor: <a href="https://ckeditor.com/cke4/addon/syntaxhighlight" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://ckeditor.com/cke4/addon/syntaxhighlight</a>, <a href="https://github.com/dbrain/ckeditor-syntaxhighlight" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/dbrain/ckeditor-syntaxhighlight</a></p>

<p> </p>

<h2>Color themes</h2>

<p>Plugin bundled with a pack of <a href="https://github.com/syntaxhighlighter/syntaxhighlighter/wiki/Brushes-and-Themes#official-themes" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">predefined color themes</a>. But you can adjust some of it to suit you needs with Cotonti theme colors. To do that copy theme CSS file from <code>syntaxhighlighter/lib/</code> folder to your theme sub folder named <code>styles</code> — <code>themes/theme-name/styles</code>. File name shoud have prefix <code>syntaxhighlighter-</code>. For example custom theme file full name can be like this: <code>themes/theme-name/styles/syntaxhighlighter-my-awesome-theme.css</code>.<br />
Now you can change it for your needs or create your own. All CSS files located in <code>themes/theme-name/styles</code> folder override default ones with same names.</p>

<p> </p>

<h2>Examples</h2>

<p>Default theme:<br />
<img alt="SyntaxHighlighter" src="https://user-images.githubusercontent.com/1021886/279939625-5c5e83ff-699d-4228-b13b-0eddc336038f.png" /></p>

<p> </p>

<p>Cotonti theme:<br />
<img alt="SyntaxHighlighter Cotonti theme" src="https://user-images.githubusercontent.com/1021886/279940162-9d9dcc26-05dc-41f9-a833-88b144d70a71.png" /></p>
]]></description>
			<pubDate>Thu, 02 Nov 2023 11:06:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/editor-parser/syntax-highlighter]]></link>
		</item>
		<item>
			<title>Maintenance Alert</title>
			<description><![CDATA[<p dir="ltr">How often do you forget to turn the Maintenance Mode back off once you finish updating your website? Thing is, when you’re done, there’s no indication that the website is actually blocked for unauthorized visits, including SE spiders.</p>

<p dir="ltr">Maintenance Alert is basically a global informer made to remind you to switch off Maintenance Mode.</p>

<p dir="ltr">Install as normal. No dependencies or configurations required.</p>

<p dir="ltr">When the MM is on, you get 2 indications:</p>

<ol dir="ltr">
	<li>A standard warning in the Admin Home location</li>
	<li>Global alert message made as a Bootstrap Toast by default with a link to the Security section in the Admin Area</li>
</ol>

<p dir="ltr">The alert message will appear everywhere, except the login location.</p>

<p dir="ltr">You can customize the alert message via message_alert.tpl template – for both front-end and back-end themes. To do that just put your templates in the plugins folders.</p>

<p dir="ltr"><img alt="" src="https://www.cotonti.com/datas/users/ma-2_183.png" /></p>
]]></description>
			<pubDate>Wed, 25 Oct 2023 10:29:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/administration-management/maintenance-alert]]></link>
		</item>
		<item>
			<title>Customavatar</title>
			<description><![CDATA[<p dir="ltr">This microplugin is used to modify default avatar picture and user avatar default class. Installation is basic. Once it is done, open plugin config and input required class (img-fluid by default) and/or change default plugin image filename if needed.</p>

<p dir="ltr">Obviously, you can do that manually by altering the relevant resource string in the userimages plugin and overwriting default avatar with your own. However, with each update you will have to do that over again.</p>
]]></description>
			<pubDate>Wed, 20 Sep 2023 16:42:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/customavatar]]></link>
		</item>
		<item>
			<title>Analogue Icon Pack</title>
			<description><![CDATA[<p>Alternative icon pack for the Cotonti Siena. To be used primarily with the admin panel.</p>

<p><img alt="Analogue Icon Pack for Cotonti Siena" src="https://www.cotonti.com/datas/users/analogue-01_183.jpg" /></p>

<h2>Features:</h2>

<ul>
	<li>Solid and one-style icons</li>
	<li>Fully compatible with the built-in Cotonti Siena admin panel</li>
	<li>Automatic replacement for the built-in &amp; some extra extensions</li>
	<li>Easy customization via resource strings</li>
</ul>

<h2>Installation:</h2>

<ol>
	<li>Copy folder to the /images/icons/ folder</li>
	<li>Alter config.php as follows:</li>
</ol>

<pre class="brush:php;">
$cfg['defaulticons'] = 'analogue';	// Default icon pack</pre>

<p><img alt="Analogue Icon Pack for Cotonti Siena" src="https://www.cotonti.com/datas/users/analogue-01_183.jpg" /> <br /> <img alt="Analogue Icon Pack for Cotonti Siena" src="https://www.cotonti.com/datas/users/analogue-02_183.jpg" /> <br /><img alt="Analogue Icon Pack for Cotonti Siena" src="https://www.cotonti.com/datas/users/analogue-03_183.jpg" /></p>
]]></description>
			<pubDate>Thu, 20 Jul 2023 07:29:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/themes/analogue]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.23 released</title>
			<description><![CDATA[<p><strong>Whats new:</strong></p>

<ul>
	<li>Added <a href="https://getcomposer.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Composer</a> support.</li>
	<li>Added PSR-4: Autoloader for classes</li>
	<li>Improved <code>cot_mail()</code> function to follow RFC 2822. Added support for several recipients, CC and BCC recipients and custom sender (from)</li>
	<li>Added check for file existence for hooks</li>
	<li>Implemented first part of logging system improvement</li>
	<li>Install - prevent execution of more than 1 process at a time</li>
	<li><a href="https://ckeditor.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">CKEditor</a> updated to v4.21.0</li>
	<li>Plugins 'BBcode Parser' and 'MarkItUp!' are removed from standard 'box'</li>
	<li>Fixed some bugs.</li>
</ul>

<p>You can find removed plugins here: <a href="https://www.cotonti.com/extensions/editor-parser/bbcode">BBCode Parser</a> and <a href="https://www.cotonti.com/extensions/editor-parser/markitup">MarkItUp!</a></p>

<p>Read more on the <a href="https://www.cotonti.com/download/cotonti-siena-0923">release page</a>.</p>

<p>Thanks to everyone who participated in the work on this release, programming and testing</p>

<p> </p>

<p><strong>For more detailed info see:</strong></p>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.22...0.9.23" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/56?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.23 issues…</a></li>
</ul>

<p><a href="https://www.cotonti.com/download/cotonti-siena-0923">Learn more, download and don't forget to upgrade</a></p>
]]></description>
			<pubDate>Thu, 22 Jun 2023 09:02:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/news/announce/cotonti-siena-0923-released]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.23</title>
			<description><![CDATA[<h2>About Siena</h2>

<p>If you are a new to Cotonti — please read a brief <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">info about this CMF</a> and its <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md#requirements" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener"><strong>requirements</strong></a>.</p>

<p>See detailed <a href="https://github.com/Cotonti/Cotonti/blob/master/Install.txt" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">instructions for first-time install</a> or <a href="https://www.cotonti.com/ru/rss#ch3">updating guides</a>.</p>

<p> </p>

<h2>Release info</h2>

<h3>Whats new:</h3>

<ul>
	<li>Added <a href="https://getcomposer.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Composer</a> support.</li>
	<li>Added PSR-4: Autoloader for classes</li>
	<li>Improved <code>cot_mail()</code> function to follow RFC 2822. Added support for several recipients, CC and BCC recipients and custom sender (from)</li>
	<li>Added check for file existence for hooks</li>
	<li>Implemented first part of logging system improvement</li>
	<li>Install - prevent execution of more than 1 process at a time</li>
	<li><a href="https://ckeditor.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">CKEditor</a> updated to v4.21.0</li>
	<li>Plugins 'BBcode Parser' and 'MarkItUp!' are removed from standard 'box'</li>
	<li>Fixed some bugs.</li>
</ul>

<p>You can find removed plugins here: <a href="https://www.cotonti.com/extensions/editor-parser/bbcode">BBcode Parser</a> and <a href="https://www.cotonti.com/extensions/editor-parser/markitup">MarkItUp!</a></p>

<p> </p>

<h3>For more detailed info see:</h3>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.22...0.9.23" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/56?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.23 issues…</a></li>
</ul>

<p> </p>

<h2>Updating from previous versions</h2>

<ul>
	<li>For updating from previous <strong>Siena</strong> version — see instructions <a href="https://www.cotonti.com/docs/start/updating">here</a>.</li>
	<li>For upgrading from <strong>Genoa</strong> — see <a href="https://www.cotonti.com/docs/start/updating">this document</a> (you will also need files from <a href="https://github.com/Cotonti/cotonti-legacy" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">cotonti-legacy</a> to perform the upgrade).</li>
</ul>

<p> </p>
]]></description>
			<pubDate>Thu, 22 Jun 2023 08:35:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/download/cotonti-siena-0923]]></link>
		</item>
		<item>
			<title>Comlist</title>
			<description><![CDATA[<p>Create comments lists (widgets) and publish them on the website. The widgets are generated using cot_comlist() function:</p>

<pre class="brush:xml;">
{PHP|cot_comlist($tpl, $items = 0, $order, $extra, $group = 0, $offset = 0, $pagination, $ajax_block, $cache_name, $cache_ttl)}</pre>

<p>The function accepts the following parameters:</p>

<ul>
	<li>$tpl -- template name (comlist by default)</li>
	<li>$items -- number of records (0 -- publish all)</li>
	<li>$order -- SQL-sorting (com_id DESC by default)</li>
	<li>$extra -- extra SQL-query</li>
	<li>$group -- group comments by pages (0 by default)</li>
	<li>$offset -- offset records (0 by default)</li>
	<li>$pagination -- pagination parameter name for the URL</li>
	<li>$ajax_block -- DOM block ID for ajax pagination</li>
	<li>$cache_name -- Cache name</li>
	<li>$cache_ttl -- Cache TTL</li>
</ul>

<p>The installation is standard. The Comments plugin shall be preinstalled.</p>
]]></description>
			<pubDate>Wed, 14 Jun 2023 09:06:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/comlist-sedby]]></link>
		</item>
		<item>
			<title>Nevalidate</title>
			<description><![CDATA[<p>При регистрации нового пользователя плагин до отправки формы на сервер проверяет в базе наличие введёного имени и Email под которыми пытается зарегистрироваться пользователь и в случае если такое имя или Email уже есть то выдаёт предупреждение.</p>

<p>From <a href="https://github.com/Kabak/nevalidate" rel="nofollow" rel="nofollow">GIT </a></p>

<p>Просто установите плагин и пользуйтесь</p>
]]></description>
			<pubDate>Mon, 29 May 2023 07:09:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/forms-feedback/nevalidate]]></link>
		</item>
		<item>
			<title>Coding Style</title>
			<description><![CDATA[<p>The following code style is used for Cotonti CMF core and official extensions development. If you want to pull-request code into the core, consider using it. We aren't forcing you to use this code style for your application based on Cotonti. Feel free to choose what suits you better.</p>

<h2>General rules</h2>

<p>This common rules consider all source code files in the project (HTML, PHP, CSS, JS, etc.) if other is not defined.</p>

<ul>
	<li>Code files MUST use only UTF-8 encoding without BOM.</li>
	<li>A new line SHOULD be LF.</li>
	<li>Indentation SHOULD be 4 spaces for indenting, not tabs.</li>
	<li>No extra spaces at the end of lines (set up your text editor, so that it removes extra spaces when saving).</li>
</ul>

<p>There is not a hard limit on line length. Each line of text in your code should be at most 120 characters long.  <br />
Put the line break wherever it makes the most aesthetic sense, not necessarily the breaking point closest to 120 characters.</p>

<p> </p>

<h2>PHP guidelines</h2>

<h3>A brief view</h3>

<p><em>…in addition to general rules</em></p>

<p>PHP code should follow the <a href="https://www.php-fig.org/psr/psr-12/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PSR-12</a>, and the <a href="https://www.php-fig.org/psr/psr-1/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PSR-1</a> coding standards and the <a href="https://www.php-fig.org/psr/psr-4/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PSR-4</a> autoloading standard.</p>

<p>If you are using PhpStorm, it can help you to maintain the required code style. You can turn it on in <code>Settings</code> → <code>Editor</code> → <code>Code Style</code> → <code>PHP</code> → <code>Set from</code> → <code>PSR12</code>.</p>

<ul>
	<li>PHP code MUST use either <code>&lt;?php</code> or <code>&lt;?=</code> opening tags and MUST NOT use the other tag variations such as <code>&lt;?</code>.</li>
	<li>In case file contains PHP only it should not have trailing <code>?&gt;</code>.</li>
	<li>Use one space around all operators, except for increment/decrement, e.g. <code>$a + $b</code>, <code>$string = $foo . 'bar'</code>, <code>$i++</code>, not <code>$a+$b</code>.</li>
	<li>Use one space after comma <code>$one, $two</code>, but not <code>$one,$two</code>.</li>
	<li>Use strict equality <code>===</code> (inequality <code>!==</code>).</li>
	<li>It is recommended to enable strict typing in new files using the <code>declare(strict_types=1);</code> directive.</li>
	<li>One-line comments should be started with <code>//</code> and not <code>#</code>.</li>
	<li>Avoid using global variables. Don't use undefined variables.</li>
</ul>

<h3>Documentation</h3>

<ul>
	<li>Refer to <a href="https://phpdoc.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHPDoc</a> for documentation syntax.</li>
	<li>Code without documentation is not allowed.</li>
	<li>All class files must contain a "file-level" docblock at the top of each file and a "class-level" docblock immediately above each class.</li>
</ul>

<h4>File Header</h4>

<p>All PHP files should contain some documentation info formatted as <a href="https://phpdoc.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHPDoc</a>.</p>

<p>It is very good when the header describes the variables that are used in this file, but are defined somewhere else.</p>

<p>Standard header for new files (this template of the header must be included at the start of all Cotonti files):</p>

<pre class="brush:php;">
/**
 * @package {PACKAGENAME}
 * @version {VERSION}
 * @copyright (c) 2008-2023 Cotonti Team
 * @license BSD License
 * 
 * @var array&lt;string, mixed&gt; $user
 * @var XTemplate $t
 */</pre>

<p><code>@version</code> is optional. For example, if you are developing some extension, you do not need to define <code>@version</code> tag as version info already set in extension setup file and may confuse other developers.</p>

<h4>Classes</h4>

<p>Do not forget to comment the class. Classes need a separate @package definition, it is the same as the header package name.</p>

<pre class="brush:php;">
/**
 * Cotonti MySQL Database adapter class.
 * A compact extension to standard PHP PDO class with slight Cotonti-specific needs,
 * handy functions and query builder.
 * 
 * @package cotonti
 * @see http://www.php.net/manual/en/class.pdo.php
 *
 * @property-read int $affectedRows Number of rows affected by the most recent query
 * @property-read int $count Total query count
 * @property-read int $timeCount Total query execution time
 */
class MySQL extends Adapter</pre>

<h4>Methods and functions</h4>

<p>Do not forget to comment the functions. Each function should have at least a comment of what this function does. Also, it is recommended to document the parameters too. Use <code>@param</code>, <code>@return</code>, <code>@throws</code> in that order.</p>

<pre class="brush:php;">
/**
 * Returns total number of records contained in a table
 * @param string $tableName Table name
 * @return int
 * @throws Exception if the table name is exists
 */
public function countRows($tableName)</pre>

<p>When the <code>@param</code> or <code>@return</code> attributes are redundant due to the use of native types, they can be omitted:</p>

<pre class="brush:php;">
/**
 * Execute the job.
 */
public function handle(AudioProcessor $processor): void
{
    //
}</pre>

<p>However, when the native type is generic, specify the generic type through the use of the <code>@param</code> or <code>@return</code> attributes:</p>

<pre class="brush:php;">
/**
 * Get the attachments for the post.
 * @return array&lt;int, Attachment&gt;
 */
public function attachments(int $postId): array
{
    // ...
}</pre>

<h3>Class, Function and Variable naming</h3>

<p>All names must be descriptive, but concise. Seeing the name of a class or variable, it should be clear what they are needed for. For example: <code>$CurrentUser</code>, <code>getUserData($id)</code>.</p>

<p><strong>Class names</strong> MUST be declared in <strong>PascalCase</strong>. For example: <code>Controller</code>, <code>Model</code>.</p>

<p><strong>Constants</strong> MUST be declared in all upper case with underscore separators. For example: <code>STATUS_PUBLISHED</code>.</p>

<p><strong>Directory/namespace</strong> names in lower case</p>

<p>We DO NOT USE underscores to denote class private properties and methods.</p>

<h4>Variable naming</h4>

<p>Variable names MUST be in <strong>camelCase</strong>. Each word, except the first one, must begin with a capital letter. For example: <code>$currentUser</code> is correct, but <code>$current_user</code> and <code>$currentuser</code> are not.</p>

<p>Situations when one-character variable names are allowed: language strings: <code>$L</code>, string resources: <code>$R</code>, and when the variable is an index for some looping construct.</p>

<p><strong>Loop Indices</strong>:<br />
In this case, the index of the outer loop should always be <code>$i</code>. If there's a loop inside that loop, its index should be <code>$j</code>, followed by <code>$k</code>, and so on. If the loop is being indexed by some already-existing variable with a meaningful name, this guideline does not apply, example:</p>

<pre class="brush:php;">
for ($i = 0; $i &lt; $outerSize; $i++) {
  for ($j = 0; $j &lt; $innerSize; $j++) {
    foo($i, $j);
  }
}</pre>

<h4>Functions and methods names</h4>

<p>Functions and methods names MUST be in <strong>camelCase</strong>. The exception is Cotonti core functions. Good function names are <code>printLoginStatus()</code>, <code>getUserData()</code>, etc.</p>

<p>In Cotonti we are using standard <code>cot_</code> prefix for any function to avoid naming conflicts. It is standard for the core API to be reusable: <code>cot_mailPrepareAddress($address)</code>.</p>

<p>But you are not forced for use <code>cot_</code> prefix in your plugins, unless those functions are going to be reused as the core API. You can use your own prefix within your extension API.</p>

<p><strong>Function Arguments</strong> are subject to the same guidelines as variable names.</p>

<h4>Summary</h4>

<p>The basic philosophy here is to not hurt code clarity for the sake of laziness. This has to be balanced by a little bit of common sense, though: <code>printLoginStatusForAGivenUser()</code> goes too far, for example - that function would be better named <code>printUserLoginStatus()</code>, or just <code>printLoginStatus()</code>.</p>

<h3>Types</h3>

<p>All PHP types and values should be used lowercase. That includes <code>true</code>, <code>false</code>, <code>null</code>.</p>

<p>We use operators for type casting, not functions. And only their short forms. Put one space after the operator.</p>

<pre class="brush:php;">
$value1 = (int) $argument1;     // right
$value2 = (bool) $argument2;    // right

$value3 = (integer) $argument3;  // wrong
$value4 = invtal($argument2, 8); // only if it is really necessary</pre>

<p>Changing type of an existing variable is considered as a bad practice. Try not to write such code unless it is really necessary.</p>

<pre class="brush:php;">
public function save(Transaction $transaction, int $argument2 = 100)
{
  $transaction = new Connection; // bad
  $argument2 = 200; // good
}</pre>

<h3>Strings</h3>

<p>If string doesn't contain variables or single quotes, use single quotes.</p>

<pre class="brush:php;">
$str = 'Like this.';</pre>

<p>If string contains single quotes you can use double quotes to avoid extra escaping.</p>

<p><strong>Variable substitution</strong>:</p>

<pre class="brush:php;">
$str1 = "Hello $username!";
$str2 = "Hello {$username}!";</pre>

<p>The following is not permitted:</p>

<pre class="brush:as3;">
$str3 = "Hello ${username}!";</pre>

<p><strong>Concatenation</strong></p>

<p>Add spaces around dot when concatenating strings:</p>

<pre class="brush:php;">
$name = 'Cotonti' . ' CMF';</pre>

<p>When string is long format is the following:</p>

<pre class="brush:php;">
$sql = 'SELECT * '
. 'FROM post '
. 'WHERE id = 121 ';</pre>

<h3>Arrays</h3>

<p>For arrays we're using short array syntax.</p>

<pre class="brush:php;">
$arr = [3, 14, 15, 'Cotonti', 'CMF'];</pre>

<p>If there are too many elements for a single line, each element is located on a separate line. After the last element we put a comma.</p>

<pre class="brush:php;">
$mail = [
  'to'  =&gt; 'user@domain.com',
  'from' =&gt; ['admin@site.com', 'SiteTitle'],
  'cc' =&gt; [['user2@example.com', 'User2'], 'user3@example.com', 'User4 &lt;user4@example.com&gt;'],
];</pre>

<h3>Control Structures</h3>

<ul>
	<li>Control statement condition MUST have single space before and after parenthesis.</li>
	<li>Operators inside of parenthesis SHOULD be separated by one space.</li>
	<li>Opening brace MUST be on the same line.</li>
	<li>The closing brace MUST be on the next line after the body.</li>
	<li>Always use braces for single line statements.</li>
</ul>

<h4>if, elseif, else</h4>

<pre class="brush:php;">
if ($expr1) {
  // if body
} elseif ($expr2) {
  // elseif body
} else {
  // else body;
}

// The following is NOT allowed:
if (!$model &amp;&amp; null === $event) throw new Exception('test');</pre>

<p>The keyword <code>elseif</code> SHOULD be used instead of <code>else if</code> so that all control keywords look like single words.</p>

<p>Expressions in parentheses MAY be split across multiple lines, where each subsequent line is indented at least once. When doing so, the first condition MUST be on the next line. The closing parenthesis and opening brace MUST be placed together on their own line with one space between them. Boolean operators between conditions MUST always be at the beginning of the line.</p>

<pre class="brush:php;">
if (
  $expr1
  &amp;&amp; $expr2
) {
  // if body
}</pre>

<p>Prefer avoiding <code>else</code> after <code>return</code> where it makes sense:</p>

<pre class="brush:php;">
$result = $this-&gt;getResult();
if (empty($result)) {
  return false;
} else {
  // process result
}</pre>

<p>is better as:</p>

<pre class="brush:php;">
$result = $this-&gt;getResult();
if (empty($result)) {
  return false;
}

// process result</pre>

<h4>switch, case</h4>

<p>A <code>switch</code> structure looks like the following. Note the placement of parentheses, spaces, and braces.</p>

<pre class="brush:php;">
switch ($expr) {
  case 0:
    echo 'First case, with a break';
    break;
  case 1:
    echo 'Second case, which falls through';
    // no break
  case 2:
  case 3:
  case 4:
    echo 'Third case, return instead of break';
    return;
  default:
    echo 'Default case';
}</pre>

<h4>Ternary operator</h4>

<p>Ternary operators should only be used to do very simple things. Preferably, they will only be used to do assignments, and not for function calls or anything complex at all. They can be harmful to readability if used incorrectly, so don't fall in love with saving typing by using them, examples:</p>

<pre class="brush:php;">
// Bad place to use them
($i &lt; $size &amp;&amp; $j &gt; $size) ? do_stuff($foo) : do_stuff($bar);

// OK place to use them
$min = ($i &lt; $j) ? $i : $j;</pre>

<h3>Classes</h3>

<p>The term "class" refers to all classes, interfaces, and traits.</p>

<ul>
	<li>The opening brace for the class MUST go on its own line; the closing brace for the class MUST go on the next line after the body.</li>
	<li>Classes SHOULD be named using <strong>PascalCase</strong>.</li>
	<li>Every class MUST have a documentation block that conforms to the <a href="https://phpdoc.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHPDoc</a>.</li>
	<li>There should be only one class in a single PHP file.</li>
	<li>All classes should be namespaced.</li>
	<li>Visibility MUST be declared on all properties and methods.</li>
	<li>The <code>extends</code> and <code>implements</code> keywords MUST be declared on the same line as the class name. Lists of <code>implements</code> and, in the case of interfaces, <code>extends</code> MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line.</li>
</ul>

<h4>Properties</h4>

<p>Public and protected variables SHOULD be declared at the top of the class before any method declarations. Private variables should also be declared at the top of the class but may be added right before the methods that are dealing with them in cases where they are only related to a small subset of the class methods.</p>

<pre class="brush:php;">
&lt;?php

/**
 * File doc block
 */
 
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

/**
 * Class doc block
 */
class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
  public $publicProp1;
  public $publicProp2;

  protected $protectedProp;

  private $privateProp;


  public function someMethod()
  {
    // ...
  }
}</pre>

<h4>Methods and Functions</h4>

<p>Opening brace of a function SHOULD be on the line after the function declaration, and the closing brace MUST go on the next line following the body.</p>

<p>In the argument list there MUST be one space after each comma.</p>

<pre class="brush:php;">
function foo(int $arg1, string &amp;$arg2, array $arg3 = [])
{
  // function body
}</pre>

<p>Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.</p>

<pre class="brush:php;">
public function aVeryLongMethodName(
  ClassTypeHint $arg1,
  string &amp;$arg2,
  array $arg3 = []
) {
  // method body
}</pre>

<p>In the methods/functions declaration, always specify the native types of arguments and return values:</p>

<pre class="brush:php;">
// Good
/**
 * Execute the job.
 */
public function handle(AudioProcessor $processor): void
{
    //
}


// Not good
/**
 * Execute the job.
 * @param AudioProcessor processor
 * @return void
 */
public function handle($processor)
{
    //
}

// Bad
/**
 * Execute the job.
 */
public function handle($processor)
{
    //
}</pre>

<p>When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis, there MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma.</p>

<h2>SQL guidelines</h2>

<p>SQL Statements are often unreadable without some formatting, since they tend to be big at times. Though the formatting of sql statements adds a lot to the readability of code. SQL statements should be formatted in the following way, basically writing keywords:</p>

<pre class="brush:php;">
$sql = 'SELECT p.*, u.* ' 
    . 'FROM ' . Cot::$db-&gt;pages . ' AS p ' .
    . 'LEFT JOIN ' . Cot::$db-&gt;pages . ' AS u ON u.user_id = p.page_ownerid '
    . "WHERE p.page_ownerid = 1 AND p.page_cat = 'news' " 
    . 'LIMIT 10';</pre>

<p>Use parameters to safely substitute user-supplied data into the query (even if you are sure the variable cannot contain single quotes - never trust your input):</p>

<pre class="brush:php;">
$result = Cot::$db-&gt;query(
  'SELECT * FROM ' . Cot::$db-&gt;forum_topics . ' WHERE ft_cat = :cat  AND ft_id = :topicId',
  ['cat' =&gt; $section, 'topicId' =&gt; $param]
);</pre>

<p><strong>Avoid DB specific SQL</strong></p>

<ul>
	<li>The <strong>not equals</strong> operator, as defined by the <a href="http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt" rel="nofollow" rel="nofollow">SQL-92 standard</a>, is <code>&lt;&gt;</code>. <code>!=</code> is also supported by most databases, but it's better to use <code>&lt;&gt;</code>.</li>
	<li><code>INSERT ... ON DUPLICATE KEY UPDATE</code> - is a MySQL specific extension to SQL.</li>
	<li>Backticks <code>`</code> for table and column names are MySQL specific. Better use <code>CotDB::quoteTableName()</code> and <code>CotDB::quoteColumnName()</code> or abbreviations of these methods: <code>CotDB::quoteT()</code>, <code>CotDB::quoteC()</code>.</li>
</ul>

<h2>Javascript guidelines</h2>

<ul>
	<li>Use <a href="https://jsdoc.app/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">JSDoc</a> for classes, member variables, and methods</li>
	<li>The documenting, commenting and naming rules are applicable from point 2. PHP</li>
	<li>Don't use <a href="https://jquery.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">jQuery</a> where you can do without it.</li>
	<li>Use <code>let</code> rather than <code>var</code> to declare variables and <code>const</code> to declare constants.</li>
	<li>Constants whose values are always hard-coded throughout the program are named in uppercase with an underscore as a word separator. For example: <code>const COLOR_ORANGE = "#ffa500"</code>. Most variables are constants in a different sense: they don't change value after assignment. But with different function launches their value may vary. Such variables should use <code>const</code> and <strong>camelCase</strong> in the name.</li>
	<li>Semicolons are always placed at the end of the line.</li>
	<li>Always use strict equality <code>===</code> (inequality <code>!==</code>).</li>
</ul>

<h3>Strings</h3>

<ul>
	<li>use single quotes: <code>let single = 'single-quoted';</code>.</li>
	<li>If string contains single quotes you can use double quotes to avoid extra escaping.</li>
	<li>For expressions substitute use backticks: <code>alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.</code>.</li>
</ul>

<h2>Helpful links and tools</h2>

<ul>
	<li><a href="https://www.jetbrains.com/help/phpstorm/php-quality-tools.html" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHPStorm Quality Tools</a></li>
	<li><a href="https://phpstan.org/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHP Static Analysis Tool</a> - discover bugs in your code without running it!</li>
	<li><a href="https://github.com/squizlabs/PHP_CodeSniffer" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">PHP_CodeSniffer</a> tokenizes PHP files and detects violations of a defined set of coding standards.</li>
	<li><a href="https://keepachangelog.com/" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Changelog files rules</a> — useful how-to maintain CHANGELOG files</li>
</ul>

<p> </p>

<p><a href="https://www.cotonti.com/docs/archive/coding_style">Previous coding style version</a></p>
]]></description>
			<pubDate>Sat, 20 May 2023 06:45:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/docs/devel/code-style]]></link>
		</item>
		<item>
			<title>MarkItUp!</title>
			<description><![CDATA[<p><img alt="markitup" src="https://github.com/Cotonti-Extensions/markitup/assets/1021886/3bd6139e-1f9d-4807-85c4-c711240e6fbf" /></p>

<p>Plain BBCode content source editor using jQuery.</p>

<p>Authors:</p>

<ul>
	<li>markItUp!: <a href="https://github.com/jaysalvat" rel="nofollow" rel="nofollow">Jay Salvat</a>, <a href="https://markitup.jaysalvat.com" rel="nofollow" rel="nofollow">https://markitup.jaysalvat.com</a></li>
	<li>Cotonti plugin: Cotonti team</li>
</ul>

<p>Github: <a href="https://github.com/Cotonti-Extensions/markitup" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Cotonti-Extensions/markitup</a></p>

<p> </p>

<h2>Installation</h2>

<ul>
	<li>Download the plugin and extract "<strong>markitup</strong>" folder into your Cotonti plugins folder.</li>
	<li>Go to Administration / Extensions and install the <strong>MarkitUp!</strong> plugin.</li>
	<li>Install <a href="https://github.com/Cotonti-Extensions/bbcode" rel="nofollow" rel="nofollow">BBCode parser</a> plugin</li>
	<li>Set default markup parser <strong>BBcode</strong> in site settings: <em>https://domaint.tld/admin.php?m=config&amp;n=edit&amp;o=core&amp;p=main</em> or for pages module: <em>https://domaint.tld/admin.php?m=config&amp;n=edit&amp;o=module&amp;p=page</em>
	<p> </p>
	</li>
</ul>

<p><img alt="markitup" src="https://github.com/Cotonti-Extensions/markitup/assets/1021886/ef74008d-d223-41fe-bda0-932a5836eb8c" /></p>
]]></description>
			<pubDate>Sat, 06 May 2023 05:01:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/editor-parser/markitup]]></link>
		</item>
		<item>
			<title>BBCode Parser</title>
			<description><![CDATA[<p><em>Previously (0.9.22 and early) was included in the standard Cotonti package</em></p>

<p>Customizable support for BBCodes and smilies parsing. Adds BBCode parser support to the contents.</p>

<p>Authors: Cotonti Team</p>

<p>Github: <a href="https://github.com/Cotonti-Extensions/bbcode/" rel="nofollow" rel="nofollow">https://github.com/Cotonti-Extensions/bbcode</a></p>

<p> </p>

<p><strong>BBCode</strong> ("Bulletin Board Code") is a lightweight markup language used to format messages in many Internet forum software. It was first introduced in 1998. The available "tags" of BBCode are usually indicated by square brackets (<strong>[</strong> and <strong>]</strong>) surrounding a keyword, and are parsed before being translated into HTML</p>

<p> </p>

<h2>Installation</h2>

<ul>
	<li>Download the plugin and extract "<strong>bbcode</strong>" folder into your Cotonti plugins folder.</li>
	<li>Install the plugin in Administration panel</li>
	<li>Set default markup parser in site settings: <em>https://domaint.tld/admin.php?m=config&amp;n=edit&amp;o=core&amp;p=main</em> or for pages module: <em>https://domaint.tld/admin.php?m=config&amp;n=edit&amp;o=module&amp;p=page</em></li>
	<li>Optionally install the <a href="https://www.cotonti.com/extensions/editor-parser/markitup">MarkItUp!</a> editor with bbcode support</li>
</ul>

<p> </p>

<h2>BBCodes examples</h2>

<div class="pretty">
<table style="table-layout:fixed;">
	<thead>
		<tr>
			<th>BBCode</th>
			<th>Example in HTML/CSS</th>
			<th>Output</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>[b]bolded text[/b]</td>
			<td><code>&lt;strong&gt;bolded text&lt;/strong&gt;</code></td>
			<td><strong>bolded text</strong></td>
		</tr>
		<tr>
			<td>[i]italicized text[/i]</td>
			<td><code>&lt;em&gt;italicized text&lt;/em&gt;</code></td>
			<td><em>italicized text</em></td>
		</tr>
		<tr>
			<td>[u]underlined text[/u]</td>
			<td><code>&lt;span style="text-decoration: underline;"&gt;underlined text&lt;/span&gt;</code></td>
			<td><u>underlined text</u></td>
		</tr>
		<tr>
			<td>[s]strikethrough text[/s]</td>
			<td><code>&lt;span style="text-decoration: line-through;"&gt;strikethrough text&lt;/span&gt;</code></td>
			<td><del>strikethrough text</del></td>
		</tr>
		<tr>
			<td>[center]center align[/center]</td>
			<td><code>&lt;div style="text-align:center"&gt;center align&lt;/div&gt;</code></td>
			<td> </td>
		</tr>
		<tr>
			<td>[right]right align[/right]</td>
			<td><code>&lt;div style="text-align:right"&gt;right align&lt;/div&gt;</code></td>
			<td> </td>
		</tr>
		<tr>
			<td>[justify]justify align[/justify]</td>
			<td><code>&lt;div style="text-align:justify"&gt;justify align&lt;/div&gt;</code></td>
			<td> </td>
		</tr>
		<tr>
			<td>[url=https://en.wikipedia.org]English Wikipedia[/url]</td>
			<td><code>&lt;a href="https://en.wikipedia.org"&gt;English Wikipedia&lt;/a&gt;</code></td>
			<td><a href="https://en.wikipedia.org" rel="nofollow" rel="nofollow">English Wikipedia</a></td>
		</tr>
		<tr>
			<td>[img]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img]</td>
			<td><code>&lt;img src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" /&gt;</code></td>
			<td><img alt="" src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" /></td>
		</tr>
		<tr>
			<td>[spoiler]Text behind the spoiler[/spoiler]</td>
			<td> </td>
			<td> </td>
		</tr>
		<tr>
			<td>[hide]Text for authorized users[/hide]</td>
			<td> </td>
			<td> </td>
		</tr>
	</tbody>
</table>
</div>

<p>and much more...</p>

<p>All available bbcodes you can find in the plugin admin panel <em>https://domaint.tld/admin.php?m=other&amp;p=bbcode</em>. You can also add your own ones.</p>

<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="border:;height:initial;min-width:initial;max-width:initial;min-height:initial;max-height:initial;margin:auto;width:initial;font-size:13px;font-family:'X-LocaleSpecific', sans-serif, Tahoma, Helvetica;line-height:13px;vertical-align:top;">
<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_logo" title="Перевести выделенный фрагмент"> </div>

<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_sound" title="Прослушать"> </div>

<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" title="Скопировать текст в буфер обмена"> </div>
</div>
]]></description>
			<pubDate>Sat, 06 May 2023 05:01:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/editor-parser/bbcode]]></link>
		</item>
		<item>
			<title>Alpha Filters</title>
			<description><![CDATA[<p>The <strong>Alpha Filters</strong> plugin gives you a flexible capability to filter pages &amp; users by letters, numbers and letter combinations (syllable-based). You can also assign your own styles to the filter span elements.</p>

<p> </p>

<p>Authors: <a href="https://www.cotonti.com/users/esclkm">esclkm</a>, <a href="https://lily-software.com" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Kalnov Alexey</a>, Cotonti Team</p>

<p>Github: <a href="https://github.com/Alex300/cotonti-alphafilters" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">https://github.com/Alex300/cotonti-alphafilters</a></p>

<p> </p>

<h2>Installation</h2>

<ul>
	<li>Unpack to your plugins folder</li>
	<li>Install the plugin in AdminCP</li>
	<li>Add tags to <strong>page.list.tpl</strong> and/or <strong>users.tpl</strong></li>
	<li>Customize plugin configuration if necessary</li>
</ul>

<p> </p>

<p>Example for users.tpl:</p>

<pre class="brush:xml;">
&lt;!-- IF {PHP|cot_plugin_active('alphafilters')} AND {PHP.cfg.plugin.alphafilters.turnOnUsers} == 1 --&gt;
&lt;div class="margin10 small text-center"&gt;
     {PHP.L.alphafilters_byFirstLetter}:
     {ALPHAFILTER_1} {ALPHAFILTER_2}
     &lt;!-- IF {ALPHAFILTER_3} --&gt;&lt;br /&gt;{ALPHAFILTER_3}&lt;!-- ENDIF --&gt;
     {ALPHAFILTER_RESET}
&lt;/div&gt;
&lt;!-- ENDIF --&gt;</pre>

<p> </p>

<p>Plugin example:</p>

<p> </p>

<p><img alt="" src="https://user-images.githubusercontent.com/1021886/235350669-1ae221e6-5489-4fda-ae8c-27470b96bbbf.png" style="width:820px;" /></p>
]]></description>
			<pubDate>Mon, 01 May 2023 08:04:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/navigation-structure/alpha-filters]]></link>
		</item>
		<item>
			<title>Extensions updates</title>
			<description><![CDATA[<p>Recently, the project participants have updated a number of extensions:</p>

<p><a href="https://www.cotonti.com/extensions/administration-management/lastcommentsa">Recent comments for Administrators</a>, <a href="https://www.cotonti.com/extensions/files-media/pageavatar-siena">Pageavatar</a>, <a href="https://www.cotonti.com/extensions/navigation-structure/similar_pages">Similar Pages</a>, <a href="https://www.cotonti.com/extensions/navigation-structure/table-of-contents">Table of Contents</a>, <a href="https://www.cotonti.com/extensions/files-media/files-module">Files module</a>, <a href="https://www.cotonti.com/extensions/community-social/Users_recent_posts">User's recent posts</a>, <a href="https://www.cotonti.com/extensions/community-social/Users_pages">User's pages</a></p>

<p>Also the <a href="https://www.cotonti.com/themes/admin-panel/yukon">Yukon</a> admin panel theme was updated</p>

<p>Added new extension and theme: <a href="https://www.cotonti.com/extensions/community-social/Users_translate">User's translate</a> и <a href="https://www.cotonti.com/themes/admin-panel/adminkacota">Adminkacota</a></p>

<p>Read more details on the corresponding extensions pages.<br />
Enjoy using them :)</p>
]]></description>
			<pubDate>Thu, 20 Apr 2023 08:24:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/news/community/obnovlenie-rasshirenij]]></link>
		</item>
		<item>
			<title>User&#039;s translate</title>
			<description><![CDATA[<p>The plugin was created likeness of a series of <a href="https://www.cotonti.com/extensions/community-social/Users_pages">User's pages</a>, <a href="https://www.cotonti.com/extensions/community-social/Users_recent_posts">User's recent posts</a> plugins that expand the functionality of the user's card with materials of his authorship.</p>

<p>This plugin allows you to display the translations that users make through the work of the i18n plugin from the base engine delivery.</p>

<p> </p>

<p>Version<strong>: 0.0.1</strong><br />
GitHub: <a href="https://github.com/Dayver/usertranslate" rel="nofollow">https://github.com/Dayver/usertranslate</a><br />
<br />
<strong>Installation</strong></p>

<ul>
	<li>Unpack and upload the files into the folder : /plugins/</li>
	<li>Go into the administration panel, then the tab "Plugins", click the name of the new plugin, and at bottom of the plugin properties, select "Install all".</li>
	<li>Then in the same page, check if this plugin require new tags in the skin files (.TPL)<br />
	If yes, then open the skin file(s) with a text editor, and add the tag {USERS_DETAILS_USERTRANSLATE} in users.details.tpl .</li>
	<li>This extended plugins have their own configuration entries, available by clicking the number near "Configuration" in the plugin properties, or go directly to the main configuration tab, section "Plugins".</li>
</ul>

<p><br />
Enjoy!</p>
]]></description>
			<pubDate>Tue, 21 Mar 2023 08:20:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/extensions/community-social/Users_translate]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.22 released</title>
			<description><![CDATA[<p><strong>What's new</strong>:</p>

<ul>
	<li>Force HTTPS. If you are using HTTPS but for some reason it is not detected automatically, enable this option in config.php</li>
	<li>Ability to add attributes to included JS/CSS files via the Resources class</li>
	<li>Refactored and ordered icons and resources that use them</li>
	<li>Detailed information about PHP installed on the server (phpinfo) has been added to the admin panel</li>
	<li>CKEditor updated to version 4.20.2</li>
	<li>Minor admin panel update</li>
	<li>Fixed some missing lines in language files</li>
	<li>There is still some code that is not adapted to php 8.1. But there is less and less of it. In this release, we continued to work on this.</li>
	<li>Fixed some bugs.</li>
</ul>

<p>The '<a href="https://www.cotonti.com/extensions/navigation-structure/table-of-contents">Table Of Contents</a>' plugin has also been updated</p>

<p>There are some <strong>breaking changes</strong> and <strong>new tags</strong> in tpl files. Read more on the <a href="https://www.cotonti.com/download/cotonti-siena-0922">release page</a>.</p>

<p>Thanks to everyone who participated in the work on this release, programming and testing: <a href="https://www.cotonti.com/users/Kort">Kort</a>, <a href="https://www.cotonti.com/users/Dayver">Dayver</a>, <a href="https://www.cotonti.com/users/webitproff">webitproff</a>, <a href="https://www.cotonti.com/users/Kabak">Kabak</a> and <a href="https://www.cotonti.com/users/Alex300">Alex300</a></p>

<p> </p>

<p><strong>For more detailed info see:</strong></p>

<ul>
	<li><a href="https://www.cotonti.com/download/cotonti-siena-0922">Release page</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.21...0.9.22" rel="nofollow">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/55?closed=1" rel="nofollow">Closed 0.9.22 issues…</a></li>
</ul>

<p><a href="https://www.cotonti.com/download/cotonti-siena-0922">Learn more, download and upgrade</a></p>
]]></description>
			<pubDate>Sun, 19 Mar 2023 11:42:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/news/announce/cotonti-siena-0922-released]]></link>
		</item>
		<item>
			<title>Cotonti Siena 0.9.22</title>
			<description><![CDATA[<h2>About Siena</h2>

<p>If you are a new to Cotonti — please read a brief <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md" rel="nofollow" rel="nofollow">info about this CMF</a> and its <a href="https://github.com/Cotonti/Cotonti/blob/master/README.md#requirements" rel="nofollow" rel="nofollow"><strong>requirements</strong></a>.</p>

<p>See detailed <a href="https://github.com/Cotonti/Cotonti/blob/master/Install.txt" rel="nofollow" rel="nofollow">instructions for first-time install</a> or <a href="https://www.cotonti.com/ru/rss#ch3">updating guides</a>.</p>

<p> </p>

<h2>Release info</h2>

<h3>Whats new:</h3>

<ul>
	<li>Force HTTPS. If you are using HTTPS but for some reason it is not detected automatically, enable this option in config.php. <span class="HwtZe" lang="en" xml:lang="en"><span class="jCAhz ChMk0b"><span class="ryNqvb"><strong>Please note</strong> that during the upgrade process, the <strong>$cfg['force_https'] = FALSE</strong> (disabled by default) setting will be added to the end of the config.php</span></span></span></li>
	<li>Ability to add attributes to included JS/CSS files via the Resources class</li>
	<li>Refactored and ordered icons and resources that use them</li>
	<li>Detailed information about PHP installed on the server (phpinfo) has been added to the admin panel</li>
	<li>Minor admin panel update</li>
	<li>CKEditor updated to version 4.20.2</li>
	<li>Fixed some missing lines in language files</li>
	<li>There is still some code that is not adapted to php 8.1. But there is less and less of it. In this release, we continued to work on this.</li>
	<li>Fixed some bugs.</li>
</ul>

<p> </p>

<h3>Breaking changes:</h3>

<p>New tags in <strong>system/admin/tpl/admin.tpl:</strong></p>

<ul>
	<li>'ADMIN_BREADCRUMBS' - contains bread crumbs</li>
	<li>'ADMIN_TITLE' - now, as it should be, contains a title.</li>
</ul>

<p><strong>system/admin/tpl/admin.structure.tpl</strong>:</p>

<ul>
	<li>'ADMIN_STRUCTURE_UPDATE_DEL_URL' replaced with two new tags: 'ADMIN_STRUCTURE_DELETE_URL' and 'ADMIN_STRUCTURE_DELETE_CONFIRM_URL'</li>
	<li>'ADMIN_STRUCTURE_TPLMODE' replaced with 'ADMIN_STRUCTURE_TPL'</li>
</ul>

<p>System core info was moved to its logical location (to Other/Infos) in admin panel. So there are new tags in <strong>system/admin/tpl/admin.infos.tp</strong>l:<br />
ADMIN_INFOS_VERSION, ADMIN_INFOS_DB_VERSION, ADMIN_INFOS_DB_TOTAL_ROWS, ADMIN_INFOS_DB_INDEXSIZE, ADMIN_INFOS_DB_DATASSIZE, ADMIN_INFOS_DB_TOTALSIZE, ADMIN_INFOS_TOTALPLUGINS, ADMIN_INFOS_TOTALHOOKS</p>

<p>If you use third-party themes for admin. panels - don't forget to update them</p>

<p>File renamed: <strong>plugins/i18n/i18n.admin.extensions.php</strong> → <strong>plugins/i18n/i18n.extension.install.done.php</strong></p>

<p> </p>

<h3>For more detailed info see:</h3>

<ul>
	<li><a href="https://github.com/Cotonti/Cotonti/compare/0.9.21...0.9.22" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Commits list…</a></li>
	<li><a href="https://github.com/Cotonti/Cotonti/milestone/55?closed=1" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">Closed 0.9.22 issues…</a></li>
</ul>

<p> </p>

<h2>Updating from previous versions</h2>

<ul>
	<li>For updating from previous <strong>Siena</strong> version — see instructions <a href="https://www.cotonti.com/docs/start/updating">here</a>.</li>
	<li>For upgrading from <strong>Genoa</strong> — see <a href="https://www.cotonti.com/docs/start/updating">this document</a> (you will also need files from <a href="https://github.com/Cotonti/cotonti-legacy" rel="nofollow" target="_blank" rel="nofollow noreferrer noopener">cotonti-legacy</a> to perform the upgrade).</li>
</ul>
]]></description>
			<pubDate>Sun, 19 Mar 2023 10:20:00 -0000</pubDate>
			<link><![CDATA[https://www.cotonti.com/ru/download/cotonti-siena-0922]]></link>
		</item>
	</channel>
</rss>