Cotonti https://www.cotonti.com Open Source PHP Content Management Framework Cotonti en Mon, 10 Nov 2025 05:31:25 -0000 Varnish Cache plugin 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.

Copy the unarchived file to /plugins/ in the root directory.

Go to the plugins section in the admin panel and activate Varnish Cache.

 

Enter Varnish cache ports in plugin settings.

defaults:

Varnish host:127.0.0.0.1

Varnish admin port:80

Admin port:6082

Server port:6081

Github page: https://github.com/slaweally/Cotonti-varnish-cache/

Author: Ali Çömez / Slaweally

]]>
Mon, 23 Jun 2025 12:37:00 -0000
Reactions İcon

 

Reactions plugin allows users to give emoji-based reactions to content on pages, forums and comments.

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

Installation:
Upload the downloaded file to the plugins folder -> Admin Panel -> Plugins -> reactions -> install

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

Pages;
{PAGE_REACTIONS_BUTTONS}
{PAGE_REACTIONS_COUNTS}

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

 

]]>
Sun, 27 Apr 2025 10:23:00 -0000
Nexus Cotonti theme Nexus. Modern and mobile-friendly.

Author: Rootali

Github: https://github.com/Cotonti-Themes/nexus

Install

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

Theme Github:

Rootali: https://github.com/slaweallx/Nexus

Cotonti Theme: https://github.com/Cotonti-Themes/nexus

]]>
Tue, 22 Apr 2025 11:22:00 -0000
Turkish (TR) Language Pack for Cotonti Siena Turkish (TR) language pack for Cotonti Siena 0.9.25

Github: https://github.com/Cotonti-Langs/turkish


Please contact me by PM if you have any suggestions or corrections of this translation.

Installation:
1. Unpack the downloaded archive.
2. Copy the folders from the archive to the root directory of your website.
3. Open datas/config.php
4. Find

$cfg['defaultlang'] = 'en';

5.Replace

$cfg['defaultlang'] = 'tr';

 

]]>
Wed, 02 Apr 2025 04:38:43 -0000
Cloudflare Turnstile

Features

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

Requirements

  • Cotonti Siena v0.9.25 or later
  • Cloudflare Turnstile Site Key and Secret Key (Get keys here)

Installation

  • Upload the plugin folder turnstile into your Cotonti plugins directory: Setup is very simple, just add the following validation field to login and input fields like register, comment.

         <!-- Cloudflare Turnstile Captcha -->
         <!-- IF {USERS_AUTH_VERIFY_IMG} -->
         <tr>
             <td colspan="2" class="textcenter">
                 {USERS_AUTH_VERIFY_IMG}
                 {USERS_AUTH_VERIFY_INPUT}
             </td>
         </tr>
         <!-- ENDIF -->
    

     

    Github: Cloudflare Turnstile Plugin

    Plugin Page: Cotonti Cloudflare Turnstile Plugin

]]>
Sat, 08 Mar 2025 05:12:00 -0000
Accepting payments Accepting payments.

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.

This can be implemented using the "Payments" module.

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

$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' => $months * 30 * 24 * 60 * 60,
    
    // Optional. Description or purpose of the payment.
    'desc' => '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' => $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&n=history
    'redirect' => cot_url('extension-code', ['m' => 'orders', 'id' => $orderId], '', true)
]

cot_payments_create_order($area, $amount, $options);

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

The cot_payments_create_order() 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.

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.

Payments

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

At the moment when the payment status changes to "Paid" the payments.payment.success hook is triggered.
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 cot_payments table containing the payment record being processed..

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.

To display any information to the user, you need to use the URL passed through $options['redirect'], 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.

To test your extension integration with the payment module, you can use the Nullbilling plugin. It is a plugin with a test payment system that does not make any payments, but simulates a successful payment.

Connecting payment systems

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.

Let's consider creating such a plugin.

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

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

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 input hook handler with the following code:

if (
    isset($_GET['e'])
    && $_GET['e'] === 'myPaymentSystem'
    && isset($_GET['a'])
    && $_GET['a'] === 'notify'
    && $_SERVER['REQUEST_METHOD'] === 'POST'
) {
    define('COT_NO_ANTIXSS', 1) ;
    Cot::$cfg['referercheck'] = false;
}

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

The plugin has a standalone 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 admin.extensions.plug.list.loop hook handler:

if ($type === COT_EXT_TYPE_PLUGIN && $code === 'myPaymentSystem') {
    $t->assign([
        'ADMIN_EXTENSIONS_JUMPTO_URL' => null,
    ]);
}

And to admin.extensions.details hook:

if ($type === COT_EXT_TYPE_PLUGIN && $code === 'myPaymentSystem') {
    $standalone = null;
    $t->assign([
        'ADMIN_EXTENSIONS_JUMPTO_URL' => $standalone,
    ]);
}

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 admin.config.edit.tags hook

if ($o === COT_EXT_TYPE_PLUGIN && $p === 'myPaymentSystem') {
    $adminHelp = '... Справка по настройке платежной системы ...';
}

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

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 cot_payments table.

Get the payment data:

// Get payment ID
$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));

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.

Many payment systems allow to transfer URLs in the payment initialization parameters, where needed to redirect the user after payment. You can get them using the following methods: successful payment url - PaymentService::getSuccessUrl($PaymentId) and the fail payment URL - PaymentService::getFailUrl($paymentId).

Before redirecting the user to the payment system's website to make a payment, set the local payment status "In progress" and specify which payment system processes the payment.

PaymentService::setStatus(
    $paymentId,
    PaymentDictionary::STATUS_PROCESS,
    'myPaymentSystem',
    PaymentDictionary::METHOD_CARD,
    $psPaymentId
);

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.

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:

$psPaymentId = $paymentId . '-' . time();

We save it in the cot_payments table, passing the 5th parameter to PaymentService::setStatus().

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 standalone hook, you can also do it in the ajax hook.

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 "Paid"

PaymentService::setStatus(
    $paymentId,
    PaymentDictionary::STATUS_PAID,
    'myPaymentSystem',
    null,
    null,
    $transactionId
)

here we skip the parameters $paymentMethod, $paymentSystemPaymentId - they were set earlier. But we pass $transactionId (optional) - the identifier of the transaction (or payment) on the payment system side. Most payment systems pass it with payment notification (web-hook).

]]>
Mon, 07 Oct 2024 18:16:00 -0000
Using captcha in extensions 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.

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.

Using a captcha in your extensions is pretty simple.

To display a captcha in any form:

Add such code to the your extension's controller:

// 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 && !empty($cot_captcha)) {
	// Output captcha to the template
	$t->assign(cot_generateCaptchaTags(null, 'rverify', 'FEEDBACK_FORM_'));
}

Add tags to the template for captcha output:

<!-- IF {FEEDBACK_FORM_VERIFY_IMG} -->
<div>
	{FEEDBACK_FORM_VERIFY_IMG} {FEEDBACK_FORM_VERIFY_INPUT}
</div>	
<!-- ENDIF -->

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

if (Cot::$usr['id'] === 0 && !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');
	}
}
]]>
Mon, 07 Oct 2024 04:56:00 -0000
SecurImage Captcha

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

Uses the Securimage class (from Drew Phillips)

Authors:

Github: https://github.com/Alex300/SecurImageCaptcha-for-Cotonti

Plugin page on author's site: https://lily-software.com/free-scripts/cotonti-securImage-captcha

Opportunities:

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

A sample of the captcha's work can be viewed, for example, in the registration form of this site.

Installation:

  • copy the captcha folder from the archive to the plugins folder on your hosting
  • install the plugin in the ite admin panel
  • in the site admin panel, under Configuration -> Security -> Captcha, select default "Captcha"

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

Using captchas in your plugins:

Similar to using any other captcha.

 

]]>
Sun, 06 Oct 2024 05:33:00 -0000
Freelance Exchange bundle 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.

Authors: Bulat Yusupov и CMSWorks team, Cotonti team
GitHub: https://github.com/Cotonti-Extensions/freelance

Main features

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: Interkassa, Robokassa 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.

Extensions from this bundle can be installed on existing sites and used individually and only those ones that you need.

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. This particular option is described below.

Preparing for install

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 Download section.

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

Install

  • Open your browser and follow the link: http://your-domain.tld/install.php (replace your-domain.tld with your domain)
  • Follow the on-screen instructions until the installation is complete. During installation, select the flance installation script and bootlance theme.
  • 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.
  • In the file datas/config.php set the option $cfg['customfuncs'] = true;
  • Be sure to configure the Usergroupselector 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.
  • 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 Mavatars and Mavatarslance plugins, which also come as part of the bundle.
  • Initially, your site will be empty. You can create your own categories yourself in the "Structure" section of the admin panel.

Learn more about the possibilities of the Freelance Exchange bundle

Jobs

Projects module

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.

Marketplace

Market module
A sectionforplacingready-to-sellgoodsorservices of the user.Eachproductcontains:title,description,imageandprice. Also, allproducts/services are categorizedin the catalogforeasysearch.

Accepting payments

Payments module

This module is a universal mechanism that allows you to accept payments on your site.

Payments are accepted through Robokassa, Interkassa and WebMoney systems. Connecting other payment systems should not cause serious difficulties for developers.

You can use this module to accept payments in your extensions.

In addition, optionally, each user can have their own personal account on the site with which they can pay for paid services.

Users Portfolios

Folio module
Allows users to exhibit their work as a portfolio. Optionally, the works can be pre-moderated before publication.

Secure settlement system (Risk-free transactions)

Sbr plugin
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.

User roles (groups)

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.

Reviews

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.

User's ratings

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.

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.

Paid services

PRO (premium) account (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); A paid place on the main page and in any other place on the site (price per placement). Ad blocks 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.

Categories

The site's admin panel allows you to edit categories for all parts of the site, including: 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.

]]>
Tue, 24 Sep 2024 16:40:00 -0000
Database Introduction

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

Currently support is provided for MySQL 5.1+

Configuration

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

Running SQL Queries

You can get access to the Cotonti database connection instance with the facade class Cot. The Cotonti database object is built on top of the PDO and provides method for executing database queries and methods that simplify the construction of INSERT, UPDATE and DELETE queries.

You can execute a SQL query by taking the following steps:

  1. Create a plain SQL query;
  2. Bind parameters (optional);
  3. Call one of the SQL execution methods in PDOStatement class.

The following example shows various ways of fetching data from a database:

// 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->query('SELECT * FROM post')->fetchAll();

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

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

For queries that do not return data, you should call the PDOStatement::execute() method instead. For example:

Cot::$db->query('UPDATE post SET status=1 WHERE id=1')->execute();

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

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

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

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

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

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

update() and delete() 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.

In the example above:

$condition = [
	"created_at < '2024-07-08 12:45:56'",
	'category = :category'
];

is equivalent to:

(created_at < '2024-07-08 12:45:56') AND (category = :category)

Binding Parameters

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

$post = Cot::$db->query(
	'SELECT * FROM post WHERE category = ? AND status = ?',
	[$category, status]
)->fetch();

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

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

$post = Cot::$db->query('SELECT * FROM post WHERE category = ?', $category)->fetch();

You can use scalar parameters:

$post = Cot::$db->query(
	'SELECT * FROM post WHERE id = :id AND status = :status',
	['id' => $id, ':status' => status]
)->fetch();

Quoting Table and Column Names

Cot::$db->query(
    'SELECT * FROM ' . Cot::$db->quoteTableName(Cot::$db->pages) 
    . ' WHERE page_cat = ' . Cot::$db->quote($category)
)->fetchColumn();

Quoting methods:

  • Cot::$db->quoteTableName() or short version (Cot::$db->quoteT())
    Quotes a table name for use in a query. If the table name contains schema prefix, the prefix will also be properly quoted.
  • Cot::$db->quoteColumnName() or short version (Cot::$db->quoteC())
    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.
  • Cot::$db->quote()
    Quotes a string value for use in a query. It is recommended to use parameter binding instead of this method, if possible.

Database Transactions

You may use the Cot::$db->transaction() 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:

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

Manually Using Transactions

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

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

Specifying Isolation Level

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:

$isolationLevel = \cot\database\DataBaseDictionary::REPEATABLE_READ;

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

Cot::$db->beginTransaction($isolationLevel);

Handling Deadlocks

The Cot::$db->transaction() 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:

Cot::$db->transaction(
	function(): void 
	{
		....
	},
	$isolationLevel,
	5
);

Working with Database Schema

(section being updated)

Cotonti database object provides several methods to work with database schema:

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

Execution of SQL scripts

The CotDB::runScript($script, $translaction = false) method allows you to execute SQL scripts (contents of SQL files). Table names must be escaped with the MySQL escape symbol ` and have the cot_ prefix, which will be replaced with the prefix from the settings in datas/config.php.

]]>
Sun, 08 Sep 2024 14:51:00 -0000
Cotonti Siena 0.9.25 released 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.

Whats new:

  • Support for Php 5.x has been discontinued. The minimum Php version is 7.3
  • Database: transactions support with nesting control
  • cot_user_sqlExcludeBanned() for generate sql condition to exclude banned users. You can use it your extensions.
  • cot_generateCaptchaTags() captcha tag generation unification for the coTemplate
  • Legacy mode ($cfg['legacyMode']) to turn on deprecated features. You can use it if your extensions and/or theme are not fully compatible with the current Cotonti version. Turned off by default.
  • Many minor improvements and fixes

Read more on the release page.

Thanks to everyone who participated in the work on this release, programming and testing

 

For more detailed info see:

]]>
Tue, 03 Sep 2024 06:10:00 -0000
Cotonti Siena 0.9.25 About Siena

If you are a new to Cotonti — please read a brief info about this CMF and its requirements.

See detailed instructions for first-time install or updating guides.

 

Release info

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.

Whats new:

  • Support for Php 5.x has been discontinued. The minimum Php version is 7.3
  • Database: transactions support with nesting control
  • cot_user_sqlExcludeBanned() for generate sql condition to exclude banned users. You can use it your extensions.
  • cot_generateCaptchaTags() captcha tag generation unification for the coTemplate
  • Legacy mode ($cfg['legacyMode']) to turn on deprecated features. You can use it if your extensions and/or theme are not fully compatible with the current Cotonti version. Turned off by default.
  • Many minor improvements and fixes

Template tags changes:

Unified captcha tags.

Unified pagination tags in pfs.admin.allpfs.tpl, polls.admin.tpl, comments.tools.tpl, ratings.admin.tpl, referers.admin.tpl, trashcan.admin.tpl:

{XXX_PAGINATION} -> {PAGINATION}
{XXX_PAGEPREV} -> {PREVIOUS_PAGE}
{XXX_PAGENEXT} -> {NEXT_PAGE}
{XXX_TOTALITEMS} -> {TOTAL_ENTRIES}
{XXX_ON_PAGE} -> {ENTRIES_ON_CURRENT_PAGE}

 

For more detailed info see:

 

Updating from previous versions

  • For updating from previous Siena version — see instructions here.
  • For upgrading from Genoa — see this document (you will also need files from cotonti-legacy to perform the upgrade).

 

 

]]>
Tue, 03 Sep 2024 05:58:00 -0000
Omnis Theme Omnis theme for Cotonti Siena

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.

Theme Demo

Dependencies

In order to implement all theme features the following extensions shall be installed:

Official Package:

  • Index
  • Page
  • Users
  • CKEditor
  • Comments system
  • Contact
  • HTML Parser
  • HTML Purifier
  • Math Captcha (or an alternative)
  • Search
  • Tags
  • User Images

3rd party:

Once the installation is complete, create a page in the system section with alias blog and title Blog. This is where all posts will be aggregated using Pagelist plugin.

To highlight a post in the feed create a page extrafield named special_class (type input). When editing such page use specialclass in the edit form to make title bolder & image bigger.

How to use the theme

My viewpoint can be found at the Omnis officlal page (Russian). Nonetheless, since in the recent poll the majority voted for modifying ready-made themes, I see two options here:

Standard

After the installation, download Omnis plugin 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.

Naturally, you are encouraged to suggest and discuss new features that will provide new functions and capabilities to the theme.

As an Intermediate Product

Unpack css-files, modify LESS code, edit markup, install other plugins, and use Omnis to make your own modifications. No offense.

Todo

So far it's sticky header and font-packed icons.

]]>
Wed, 28 Aug 2024 08:00:00 -0000
Dark Blog Необходимые плагины :

Pagelist, Catlist, Comlist, Forman, Thanks, syntaxhighlighter, attach2, nevalidate, toplastseen, Friendly functions calls

в настройках сайта

 

 

Меню #6
{PHP.cfg.menu6} во всех файлах .tpl:    количество выводимых на главной новых статей. После превышения этого числа включается паджинация

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

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

<input type="hidden" name="{$name}" value="{$value_off}" /><label><input type="checkbox" name="{$name}" value="{$value}"{$checked} /> {$title}</label>

 

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

 

Меню #7
{PHP.cfg.menu7} во всех файлах .tpl: количество последних сообщений с форуса

 

Меню #8
{PHP.cfg.menu8} во всех файлах .tpl: количество отображаемых последних статей

 

Меню #9
{PHP.cfg.menu9} во всех файлах .tpl: оличество отображаемых последних комментариев 

 

Как выглядит  ->  здесь

]]>
Tue, 20 Aug 2024 20:17:00 -0000
Using Composer

Cotonti Siena 0.9.23 features Composer support. Composer is a tool for dependency management in PHP.

What is Composer

Composer is a dependency manager 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.

composer.json 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.

composer.lock 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.

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.

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.

Using Composer to Develop Extensions

First off, make sure that Composer is installed.

Next we will add the Guzzle 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.

We will also use Flysystem to upload files into a remote storage.

These two are used only as an example with no connection between them.

Let’s begin.

We follow Guzzle installation manual to add section require into the file composer.json located in the project root:

"guzzlehttp/guzzle": "^7.8"

This would result in something like this:

"require": {
    "php": ">=5.6",
    "ext-gd": "*",
    "ext-mbstring": "*",
    "ext-json": "*",
    "ext-hash": "*",
    "ext-pdo": "*",
    "guzzlehttp/guzzle": "^7.8"
},

Next we execute the following code in the command line:

> composer update

This command updates all dependencies installed within the project to the latest version available (as per composer.json), installs new dependencies added to composer.json and removes those that no longer exist. Following that Composer updates composer.lock.

Now our HTTP client is ready for use.

Next we add the following code to our extension:

<?php

use GuzzleHttp\Client;

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

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

$body = $response->getBody();
echo $body;

Dead easy, is it?

Now we proceed to remote uploads.

As specified in the documentation we add section require to composer.json:

"league/flysystem": "^3.0",
"league/flysystem-aws-s3-v3": "^3.0"

Over again:

> composer update

Everything set. We can now use the library in our extension.

<?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' => 'latest',
    'endpoint' => 'https://storage.yandexcloud.net',
    'region' => '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->write($path, $contents);

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

"guzzlehttp/guzzle": "^7.8",
"league/flysystem": "^3.0",
"league/flysystem-aws-s3-v3": "^3.0"

Deploy Project into the Live Server

Our project is ready and is git-managed. Time to move it to the production server.

In the lib/vendor folder we got new subfolders with dependencies added by Composer. Let’s add them into the .gitignore – no need to use them in the repository and increase its size.

Now commit the changes and push them into the repository.

Next we login into the server via SSH and execute:

> git pull

Followed by:

> composer install

Unlike composer update this command shall install all dependencies listed in composer.lock and only the versions specified there. If this file is missing in the project root, this command shall act similar to composer update and use composer.json to install dependencies.

We’re done. You can now open the project in the browser and enjoy the result.

]]>
Fri, 24 May 2024 10:32:00 -0000
Project to Expire 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

TPL-tags

projects.list.tpt:

...
<!-- BEGIN: PRJ_ROWS  -->
...
Project expires in: {PRJ_ROW_PTE_TO_EXPIRE}
...
<!-- END: PRJ_ROWS  -->
...

projects.tpl:

{PRJ_PTE_TO_EXPIRE}
]]>
Fri, 26 Apr 2024 05:56:00 -0000
Cotonti Siena 0.9.24.2 released Whats new:

  • СoTemplate. Support for multiple function arguments. Now you can use other tags as function arguments. You can write like this:
    {PHP|cot_url('page', 'c=news')|var_dump({PHP.L.Home}, $this, {PHP.cfg.mainurl}, {PHP|cot_url('page', 'c=news ')}, {HEADER_TITLE})}
    The $this support is left in place. You can still use function call chains.
  • СoTemplate. Strict comparison operators: === and !==
  • Fixed a bug where data from the database cache might not be loaded automatically.
  • Static cache improvements.
  • You can now use comments in Url editor's *.dat files
  • Forums API. A new function cot_forums_sqlExcludePrivateTopics() 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.
  • The page views counter now works even when the static page cache is enabled.
  • Captcha and posting comments by guests now work when static page cache is enabled.
  • Search. The default sorting is by date descending.
  • Fixed/added meta tags title, description and canonical url in some extensions
  • Function cot_generatePaginationTags() for uniform generation of pagination tags in extensions.
  • Extrafields. Field name validation.
  • CKEditor has been updated to version 4.22.1. In future releases, it will be replaced with version 5.
  • 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.
  • The Composer folder has been moved to lib/vendor
  • 1st part of Tags plugin improvements
  • Improvements to the Recent items plugin
  • Other minor improvements
  • Fix for various errors found during operation.

Read more on the release page.

Thanks to everyone who participated in the work on this release, programming and testing

 

For more detailed info see:

]]>
Fri, 02 Feb 2024 12:43:00 -0000
Cotonti Siena 0.9.24.2 About Siena

If you are a new to Cotonti — please read a brief info about this CMF and its requirements.

See detailed instructions for first-time install or updating guides.

 

Release info

Whats new:

  • СoTemplate. Support for multiple function arguments. Now you can use other tags as function arguments. You can write like this:
    {PHP|cot_url('page', 'c=news')|var_dump({PHP.L.Home}, $this, {PHP.cfg.mainurl}, {PHP|cot_url('page', 'c=news ')}, {HEADER_TITLE})}
    The $this support is left in place. You can still use function call chains.
  • СoTemplate. Strict comparison operators: === and !==
  • Fixed a bug where data from the database cache might not be loaded automatically.
  • Static cache improvements.
  • You can now use comments in Url editor's *.dat files
  • Forums API. A new function cot_forums_sqlExcludePrivateTopics() 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.
  • The page views counter now works even when the static page cache is enabled.
  • Captcha and posting comments by guests now work when static page cache is enabled.
  • Search. The default sorting is by date descending.
  • Fixed/added meta tags title, description and canonical url in some extensions
  • Function cot_generatePaginationTags() for uniform generation of pagination tags in extensions.
  • Extrafields. Field name validation.
  • CKEditor has been updated to version 4.22.1. In future releases, it will be replaced with version 5.
  • 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.
  • The Composer folder has been moved to lib/vendor
  • 1st part of Tags plugin improvements
  • Improvements to the Recent items plugin
  • New setting in config.php: $cfg['legacyMode']. If false, it disables all deprecated functionality.
  • Other minor improvements
  • Fix for various errors found during operation.

 

Template tags changes:

Unified captcha tags:

users.register.tpl
{USERS_REGISTER_VERIFYIMG} -> {USERS_REGISTER_VERIFY_IMG}
{USERS_REGISTER_VERIFYINPUT} -> {USERS_REGISTER_VERIFY_INPUT}

comments.tpl
{COMMENTS_FORM_VERIFYIMG} -> {COMMENTS_FORM_VERIFY_IMG}
{COMMENTS_FORM_VERIFY} -> {COMMENTS_FORM_VERIFY_INPUT}

contact.tpl
{CONTACT_FORM_VERIFY} -> {CONTACT_FORM_VERIFY_INPUT}

 

Unified pagination tags:
{<prefix>PAGINATION}
{<prefix>PREVIOUS_PAGE}
{<prefix>NEXT_PAGE}
{<prefix>CURRENT_PAGE}
{<prefix>TOTAL_ENTRIES}
{<prefix>ENTRIES_ON_CURRENT_PAGE}
{<prefix>ENTRIES_PER_PAGE}
{<prefix>TOTAL_PAGES}

<prefix> can be empty. Or not, if there are more than one paginations on the page.
For example on page.list.tpl:

{LIST_CAT_PAGINATION} for categories list and {PAGINATION} for pages list.


forums.posts.tpl
{FORUMS_POSTS_BREADCRUMBS} - new
{FORUMS_POSTS_SHORTTITLE} -> {FORUMS_POSTS_TITLE}
{FORUMS_POSTS_PAGETITLE} -> {PAGEEDIT_FORM_DESCRIPTION}


all user tags tags: {FORUMS_POSTS_ROW_USERXXX} -> {FORUMS_POSTS_ROW_USER_XXX}
e.g.
{FORUMS_POSTS_ROW_USERNAME} -> {FORUMS_POSTS_ROW_USER_NAME}
{FORUMS_POSTS_ROW_USERAVATAR} -> {FORUMS_POSTS_ROW_USER_AVATAR}
etc.

{PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE} and other pagination tags without prefix

 

polls.admin.tpl
{ADMIN_POLLS_ROW_POLL_URL_DEL} deprecated
{ADMIN_POLLS_ROW_POLL_DELETE_URL} - new
{ADMIN_POLLS_ROW_POLL_DELETE_CONFIRM_URL} - new

 

system/admin/tpl/admin.extensions.tpl
{ADMIN_EXTENSIONS_DETAILS_ROW_ORDER_INSTALLED}
{ADMIN_EXTENSIONS_DETAILS_ROW_HOOKS_INSTALLED}

 

page.list.tpl (same changes in cot_page_enum())
{LIST_CATTITLE} -> {LIST_BREADCRUMBS} - new
{LIST_BREADCRUMBS_SHORT} - new
{LIST_ROWCAT_URL} -> {LIST_CAT_ROW_URL}
{LIST_ROWCAT_TITLE} -> {LIST_CAT_ROW_TITLE}
{LIST_ROWCAT_COUNT} -> {LIST_CAT_ROW_COUNT}
{LIST_ROWCAT_DESC} -> {LIST_CAT_ROW_DESCRIPTION}

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

Block LIST_ROWCAT -> LIST_CAT_ROW

{LIST_ROW_XXX} - page tags see below.


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


page.add.tpl
{PAGEADD_FORM_DESC} -> {PAGEADD_FORM_DESCRIPTION}
{PAGEADD_FORM_OWNERID} -> {PAGEADD_FORM_OWNER_ID}

 

page.edit.tpl
{PAGEEDIT_FORM_LOCALSTATUS} -> {PAGEEDIT_FORM_LOCAL_STATUS}
{PAGEEDIT_FORM_DESC} -> {PAGEEDIT_FORM_DESCRIPTION}
{PAGEEDIT_FORM_OWNERID} -> {PAGEEDIT_FORM_OWNER_ID}
{PAGEEDIT_FORM_PAGECOUNT} -> {PAGEEDIT_FORM_HITS}
{PAGEEDIT_FORM_FILECOUNT} -> {PAGEEDIT_FORM_FILE_DOWNLOADS}


pm.list.tpl, pm.message.tpl
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...

 

polls.admin.tpl
{ADMIN_POLLS_ROW_POLL_DELETE_CONFIRM_URL} - new
{ADMIN_POLLS_ROW_POLL_URL_DEL} -> {ADMIN_POLLS_ROW_POLL_DELETE_URL}


users.edit.php
{USERS_EDIT_TITLE} - now it is a page title
{USERS_EDIT_BREADCRUMBS} - new
{USERS_EDIT_DETAILSLINK} -> {USERS_EDIT_DETAILS_URL}
{USERS_EDIT_MAINGRP} -> {USERS_EDIT_MAIN_GROUP}

 

users.passrecover.tpl
{PASSRECOVER_TITLE} - now it is a page title
{PASSRECOVER_BREADCRUMBS} - new

 

users.profile.tpl
{USERS_PROFILE_TITLE} - now it is a page title
{USERS_PROFILE_BREADCRUMBS} - new
{USERS_PROFILE_DETAILSLINK} -> {USERS_PROFILE_DETAILS_URL}
{USERS_PROFILE_EDITLINK} -> {USERS_PROFILE_EDIT_URL}

 

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


recentitems.tpl
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...

 

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

First poster user tags: {FORUM_ROW_FIRST_POSTER_XXX}
Last poster user tags: {FORUM_ROW_LAST_POSTER_XXX}


recentitems.pages.tpl, recentitems.pages.index.tpl, search.tpl
see page.tpl (from cot_generate_pagetags())


tags.tpl
Pagination tags without prefix: {PREVIOUS_PAGE}{PAGINATION}{NEXT_PAGE}...

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.
Also you can see a list of available tags and blocks on of the current template

 

For more detailed info see:

 

Updating from previous versions

  • For updating from previous Siena version — see instructions here.
  • For upgrading from Genoa — see this document (you will also need files from cotonti-legacy to perform the upgrade).

 

 

]]>
Sun, 28 Jan 2024 15:07:00 -0000
Editor.js Удобный, современный блочный редактор контента на основе Editor.js.

Github плагина: https://github.com/Edd-G/cot-editorjs

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

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

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

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

Пример редактора

 

 

Особенности этого плагина

  1. В оригинале Editor.js на выходе дает JSON-объект с данными каждого блока. Этот плагин, по крайней мере в текущей версии, конвертирует JSON в чистый HTML, промаркированный специальными классами. Данные в базе хранятся именно в HTML.
    Я сделал это для обратной совместимости с другими редакторами, если вам вдруг вздумается переключиться на классический редактор, вы сможете легко это сделать.
  2. Плагин пока поддерживает только модуль Pages. И только 1 экземпляр редактора на странице.
  3. Плагин размечает создаваемые HTML блоки специальными классами. Если у вас уже есть контент, и вы установите данный редактор, то парсер не найдет нужных CSS классов для рабора.
    В этом случае Editor.js сам попробует разобрать HTML. В большинстве случаев это будет довольно криво.
  4. Загрузка изображений работает пока только с помощью @editorjs/simple-image. Это значит, что добавить картинку получится только бросив ссылку на нее в редактор. Конечно можно кидать ссылки локального сервера.
  5. В текущей версии не реализована загрузка файлов. По крайней мере пока не сделали API какого-то файлового менеджера.
  6. Существует проблема с предпросмотром некотрых ссылок в @editorjs/link. Это связано с тем, что ресурс по ссылке под защитой какого-то сервиса, вроде Cloudflare. 

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

Подробнее о поддерживаемых блоках на Github.

Генерируемый плагином HTML

Header

<h2 class="prs-header prs_center">Lorem</h2>

Paragraph

<p class="prs-paragraph prs_center">
    <code class="inline-code">Pellentesque</code> 
    <i>malesuada fames</i> 
    <mark class="cdx-marker">tempus</mark>
</p>

Ordered List

<ol class="prs-list prs_ordered">
    <li></li>
</ol>

Table

<table class="prs-table prs_withheadings">
    <thead>
        <tr>
            <th>1</th><th>2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>a</td><td>b</td>
        </tr>
    </tbody>
</table>

Остальные примеры на Github

Установка плагина

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

Настройки

  1. Вы можете отключить ненужные блоки Editor.js в файле editorjs.editor.php
  2. Плагин использует свою копию HTMLpurifier. Настройте очистку данных приходящих с фронтенда с помощью правил HTML Purifier в файле sanitize-blocks-config.json Подробнее о правилах в этом файле
  3. Префикс CSS классов (по умолчанию prs) меняется в конфигурации плагина

В планах

  • Добавить выбор варианта хранения данных в базе: JSON/HTML
  • Добавить блоки для работы с изображениями и файлами
]]>
Sun, 07 Jan 2024 10:53:27 -0000
Nomerge This simple plugin lets you define forum topics where posts will not be merged. Use plugin config to specify topics number, comma-separated.

]]>
Thu, 30 Nov 2023 17:09:00 -0000
Syntax Highlighter Client side code highlighter. This is ready-to-use Cotonti port of SyntaxHighlighter by Alex Gorbatchev.

Authors:

GitHub: https://github.com/Cotonti-Extensions/syntax-highlighter

 

Installation

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

 

Usage

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

<pre class="brush:language;">
    Your code here
</pre>

 

The list of available brushes and themes: https://github.com/syntaxhighlighter/syntaxhighlighter/wiki/Brushes-and-Themes

Plugin for CKEditor: https://ckeditor.com/cke4/addon/syntaxhighlight, https://github.com/dbrain/ckeditor-syntaxhighlight

 

Color themes

Plugin bundled with a pack of predefined color themes. But you can adjust some of it to suit you needs with Cotonti theme colors. To do that copy theme CSS file from syntaxhighlighter/lib/ folder to your theme sub folder named stylesthemes/theme-name/styles. File name shoud have prefix syntaxhighlighter-. For example custom theme file full name can be like this: themes/theme-name/styles/syntaxhighlighter-my-awesome-theme.css.
Now you can change it for your needs or create your own. All CSS files located in themes/theme-name/styles folder override default ones with same names.

 

Examples

Default theme:
SyntaxHighlighter

 

Cotonti theme:
SyntaxHighlighter Cotonti theme

]]>
Thu, 02 Nov 2023 11:06:00 -0000
Maintenance Alert 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.

Maintenance Alert is basically a global informer made to remind you to switch off Maintenance Mode.

Install as normal. No dependencies or configurations required.

When the MM is on, you get 2 indications:

  1. A standard warning in the Admin Home location
  2. Global alert message made as a Bootstrap Toast by default with a link to the Security section in the Admin Area

The alert message will appear everywhere, except the login location.

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.

]]>
Wed, 25 Oct 2023 10:29:00 -0000
Customavatar 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.

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.

]]>
Wed, 20 Sep 2023 16:42:00 -0000
Analogue Icon Pack Alternative icon pack for the Cotonti Siena. To be used primarily with the admin panel.

Analogue Icon Pack for Cotonti Siena

Features:

  • Solid and one-style icons
  • Fully compatible with the built-in Cotonti Siena admin panel
  • Automatic replacement for the built-in & some extra extensions
  • Easy customization via resource strings

Installation:

  1. Copy folder to the /images/icons/ folder
  2. Alter config.php as follows:
$cfg['defaulticons'] = 'analogue';	// Default icon pack

Analogue Icon Pack for Cotonti Siena
Analogue Icon Pack for Cotonti Siena
Analogue Icon Pack for Cotonti Siena

]]>
Thu, 20 Jul 2023 07:29:00 -0000
Cotonti Siena 0.9.23 released Whats new:

  • Added Composer support.
  • Added PSR-4: Autoloader for classes
  • Improved cot_mail() function to follow RFC 2822. Added support for several recipients, CC and BCC recipients and custom sender (from)
  • Added check for file existence for hooks
  • Implemented first part of logging system improvement
  • Install - prevent execution of more than 1 process at a time
  • CKEditor updated to v4.21.0
  • Plugins 'BBcode Parser' and 'MarkItUp!' are removed from standard 'box'
  • Fixed some bugs.

You can find removed plugins here: BBCode Parser and MarkItUp!

Read more on the release page.

Thanks to everyone who participated in the work on this release, programming and testing

 

For more detailed info see:

Learn more, download and don't forget to upgrade

]]>
Thu, 22 Jun 2023 09:02:00 -0000
Cotonti Siena 0.9.23 About Siena

If you are a new to Cotonti — please read a brief info about this CMF and its requirements.

See detailed instructions for first-time install or updating guides.

 

Release info

Whats new:

  • Added Composer support.
  • Added PSR-4: Autoloader for classes
  • Improved cot_mail() function to follow RFC 2822. Added support for several recipients, CC and BCC recipients and custom sender (from)
  • Added check for file existence for hooks
  • Implemented first part of logging system improvement
  • Install - prevent execution of more than 1 process at a time
  • CKEditor updated to v4.21.0
  • Plugins 'BBcode Parser' and 'MarkItUp!' are removed from standard 'box'
  • Fixed some bugs.

You can find removed plugins here: BBcode Parser and MarkItUp!

 

For more detailed info see:

 

Updating from previous versions

  • For updating from previous Siena version — see instructions here.
  • For upgrading from Genoa — see this document (you will also need files from cotonti-legacy to perform the upgrade).

 

]]>
Thu, 22 Jun 2023 08:35:00 -0000
Comlist Create comments lists (widgets) and publish them on the website. The widgets are generated using cot_comlist() function:

{PHP|cot_comlist($tpl, $items = 0, $order, $extra, $group = 0, $offset = 0, $pagination, $ajax_block, $cache_name, $cache_ttl)}

The function accepts the following parameters:

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

The installation is standard. The Comments plugin shall be preinstalled.

]]>
Wed, 14 Jun 2023 09:06:00 -0000
Nevalidate При регистрации нового пользователя плагин до отправки формы на сервер проверяет в базе наличие введёного имени и Email под которыми пытается зарегистрироваться пользователь и в случае если такое имя или Email уже есть то выдаёт предупреждение.

From GIT 

Просто установите плагин и пользуйтесь

]]>
Mon, 29 May 2023 07:09:00 -0000
Coding Style 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.

General rules

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

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

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

 

PHP guidelines

A brief view

…in addition to general rules

PHP code should follow the PSR-12, and the PSR-1 coding standards and the PSR-4 autoloading standard.

If you are using PhpStorm, it can help you to maintain the required code style. You can turn it on in SettingsEditorCode StylePHPSet fromPSR12.

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

Documentation

  • Refer to PHPDoc for documentation syntax.
  • Code without documentation is not allowed.
  • All class files must contain a "file-level" docblock at the top of each file and a "class-level" docblock immediately above each class.

File Header

All PHP files should contain some documentation info formatted as PHPDoc.

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

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

/**
 * @package {PACKAGENAME}
 * @version {VERSION}
 * @copyright (c) 2008-2023 Cotonti Team
 * @license BSD License
 * 
 * @var array<string, mixed> $user
 * @var XTemplate $t
 */

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

Classes

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

/**
 * 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

Methods and functions

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 @param, @return, @throws in that order.

/**
 * 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)

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

/**
 * Execute the job.
 */
public function handle(AudioProcessor $processor): void
{
    //
}

However, when the native type is generic, specify the generic type through the use of the @param or @return attributes:

/**
 * Get the attachments for the post.
 * @return array<int, Attachment>
 */
public function attachments(int $postId): array
{
    // ...
}

Class, Function and Variable naming

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: $CurrentUser, getUserData($id).

Class names MUST be declared in PascalCase. For example: Controller, Model.

Constants MUST be declared in all upper case with underscore separators. For example: STATUS_PUBLISHED.

Directory/namespace names in lower case

We DO NOT USE underscores to denote class private properties and methods.

Variable naming

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

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

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

for ($i = 0; $i < $outerSize; $i++) {
  for ($j = 0; $j < $innerSize; $j++) {
    foo($i, $j);
  }
}

Functions and methods names

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

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

But you are not forced for use cot_ 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.

Function Arguments are subject to the same guidelines as variable names.

Summary

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: printLoginStatusForAGivenUser() goes too far, for example - that function would be better named printUserLoginStatus(), or just printLoginStatus().

Types

All PHP types and values should be used lowercase. That includes true, false, null.

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

$value1 = (int) $argument1;     // right
$value2 = (bool) $argument2;    // right

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

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

public function save(Transaction $transaction, int $argument2 = 100)
{
  $transaction = new Connection; // bad
  $argument2 = 200; // good
}

Strings

If string doesn't contain variables or single quotes, use single quotes.

$str = 'Like this.';

If string contains single quotes you can use double quotes to avoid extra escaping.

Variable substitution:

$str1 = "Hello $username!";
$str2 = "Hello {$username}!";

The following is not permitted:

$str3 = "Hello ${username}!";

Concatenation

Add spaces around dot when concatenating strings:

$name = 'Cotonti' . ' CMF';

When string is long format is the following:

$sql = 'SELECT * '
. 'FROM post '
. 'WHERE id = 121 ';

Arrays

For arrays we're using short array syntax.

$arr = [3, 14, 15, 'Cotonti', 'CMF'];

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.

$mail = [
  'to'  => 'user@domain.com',
  'from' => ['admin@site.com', 'SiteTitle'],
  'cc' => [['user2@example.com', 'User2'], 'user3@example.com', 'User4 <user4@example.com>'],
];

Control Structures

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

if, elseif, else

if ($expr1) {
  // if body
} elseif ($expr2) {
  // elseif body
} else {
  // else body;
}

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

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

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.

if (
  $expr1
  && $expr2
) {
  // if body
}

Prefer avoiding else after return where it makes sense:

$result = $this->getResult();
if (empty($result)) {
  return false;
} else {
  // process result
}

is better as:

$result = $this->getResult();
if (empty($result)) {
  return false;
}

// process result

switch, case

A switch structure looks like the following. Note the placement of parentheses, spaces, and braces.

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';
}

Ternary operator

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:

// Bad place to use them
($i < $size && $j > $size) ? do_stuff($foo) : do_stuff($bar);

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

Classes

The term "class" refers to all classes, interfaces, and traits.

  • 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.
  • Classes SHOULD be named using PascalCase.
  • Every class MUST have a documentation block that conforms to the PHPDoc.
  • There should be only one class in a single PHP file.
  • All classes should be namespaced.
  • Visibility MUST be declared on all properties and methods.
  • The extends and implements keywords MUST be declared on the same line as the class name. Lists of implements and, in the case of interfaces, extends 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.

Properties

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.

<?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()
  {
    // ...
  }
}

Methods and Functions

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.

In the argument list there MUST be one space after each comma.

function foo(int $arg1, string &$arg2, array $arg3 = [])
{
  // function body
}

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.

public function aVeryLongMethodName(
  ClassTypeHint $arg1,
  string &$arg2,
  array $arg3 = []
) {
  // method body
}

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

// 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)
{
    //
}

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.

SQL guidelines

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:

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

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):

$result = Cot::$db->query(
  'SELECT * FROM ' . Cot::$db->forum_topics . ' WHERE ft_cat = :cat  AND ft_id = :topicId',
  ['cat' => $section, 'topicId' => $param]
);

Avoid DB specific SQL

  • The not equals operator, as defined by the SQL-92 standard, is <>. != is also supported by most databases, but it's better to use <>.
  • INSERT ... ON DUPLICATE KEY UPDATE - is a MySQL specific extension to SQL.
  • Backticks ` for table and column names are MySQL specific. Better use CotDB::quoteTableName() and CotDB::quoteColumnName() or abbreviations of these methods: CotDB::quoteT(), CotDB::quoteC().

Javascript guidelines

  • Use JSDoc for classes, member variables, and methods
  • The documenting, commenting and naming rules are applicable from point 2. PHP
  • Don't use jQuery where you can do without it.
  • Use let rather than var to declare variables and const to declare constants.
  • Constants whose values are always hard-coded throughout the program are named in uppercase with an underscore as a word separator. For example: const COLOR_ORANGE = "#ffa500". 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 const and camelCase in the name.
  • Semicolons are always placed at the end of the line.
  • Always use strict equality === (inequality !==).

Strings

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

Helpful links and tools

 

Previous coding style version

]]>
Sat, 20 May 2023 06:45:00 -0000
MarkItUp! markitup

Plain BBCode content source editor using jQuery.

Authors:

Github: https://github.com/Cotonti-Extensions/markitup

 

Installation

  • Download the plugin and extract "markitup" folder into your Cotonti plugins folder.
  • Go to Administration / Extensions and install the MarkitUp! plugin.
  • Install BBCode parser plugin
  • Set default markup parser BBcode in site settings: https://domaint.tld/admin.php?m=config&n=edit&o=core&p=main or for pages module: https://domaint.tld/admin.php?m=config&n=edit&o=module&p=page

     

markitup

]]>
Sat, 06 May 2023 05:01:00 -0000
BBCode Parser Previously (0.9.22 and early) was included in the standard Cotonti package

Customizable support for BBCodes and smilies parsing. Adds BBCode parser support to the contents.

Authors: Cotonti Team

Github: https://github.com/Cotonti-Extensions/bbcode

 

BBCode ("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 ([ and ]) surrounding a keyword, and are parsed before being translated into HTML

 

Installation

  • Download the plugin and extract "bbcode" folder into your Cotonti plugins folder.
  • Install the plugin in Administration panel
  • Set default markup parser in site settings: https://domaint.tld/admin.php?m=config&n=edit&o=core&p=main or for pages module: https://domaint.tld/admin.php?m=config&n=edit&o=module&p=page
  • Optionally install the MarkItUp! editor with bbcode support

 

BBCodes examples

BBCode Example in HTML/CSS Output
[b]bolded text[/b] <strong>bolded text</strong> bolded text
[i]italicized text[/i] <em>italicized text</em> italicized text
[u]underlined text[/u] <span style="text-decoration: underline;">underlined text</span> underlined text
[s]strikethrough text[/s] <span style="text-decoration: line-through;">strikethrough text</span> strikethrough text
[center]center align[/center] <div style="text-align:center">center align</div>  
[right]right align[/right] <div style="text-align:right">right align</div>  
[justify]justify align[/justify] <div style="text-align:justify">justify align</div>  
[url=https://en.wikipedia.org]English Wikipedia[/url] <a href="https://en.wikipedia.org">English Wikipedia</a> English Wikipedia
[img]https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png[/img] <img src="https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png" />
[spoiler]Text behind the spoiler[/spoiler]    
[hide]Text for authorized users[/hide]    

and much more...

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

 
 
]]>
Sat, 06 May 2023 05:01:00 -0000
Alpha Filters The Alpha Filters plugin gives you a flexible capability to filter pages & users by letters, numbers and letter combinations (syllable-based). You can also assign your own styles to the filter span elements.

 

Authors: esclkm, Kalnov Alexey, Cotonti Team

Github: https://github.com/Alex300/cotonti-alphafilters

 

Installation

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

 

Example for users.tpl:

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

 

Plugin example:

 

]]>
Mon, 01 May 2023 08:04:00 -0000
Extensions updates Recently, the project participants have updated a number of extensions:

Recent comments for Administrators, Pageavatar, Similar Pages, Table of Contents, Files module, User's recent posts, User's pages

Also the Yukon admin panel theme was updated

Added new extension and theme: User's translate и Adminkacota

Read more details on the corresponding extensions pages.
Enjoy using them :)

]]>
Thu, 20 Apr 2023 08:24:00 -0000
User's translate The plugin was created likeness of a series of User's pages, User's recent posts plugins that expand the functionality of the user's card with materials of his authorship.

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

 

Version: 0.0.1
GitHub: https://github.com/Dayver/usertranslate

Installation

  • Unpack and upload the files into the folder : /plugins/
  • 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".
  • Then in the same page, check if this plugin require new tags in the skin files (.TPL)
    If yes, then open the skin file(s) with a text editor, and add the tag {USERS_DETAILS_USERTRANSLATE} in users.details.tpl .
  • 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".


Enjoy!

]]>
Tue, 21 Mar 2023 08:20:00 -0000
Cotonti Siena 0.9.22 released What's new:

  • Force HTTPS. If you are using HTTPS but for some reason it is not detected automatically, enable this option in config.php
  • Ability to add attributes to included JS/CSS files via the Resources class
  • Refactored and ordered icons and resources that use them
  • Detailed information about PHP installed on the server (phpinfo) has been added to the admin panel
  • CKEditor updated to version 4.20.2
  • Minor admin panel update
  • Fixed some missing lines in language files
  • 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.
  • Fixed some bugs.

The 'Table Of Contents' plugin has also been updated

There are some breaking changes and new tags in tpl files. Read more on the release page.

Thanks to everyone who participated in the work on this release, programming and testing: KortDayver, webitproffKabak and Alex300

 

For more detailed info see:

Learn more, download and upgrade

]]>
Sun, 19 Mar 2023 11:42:00 -0000
Cotonti Siena 0.9.22 About Siena

If you are a new to Cotonti — please read a brief info about this CMF and its requirements.

See detailed instructions for first-time install or updating guides.

 

Release info

Whats new:

  • Force HTTPS. If you are using HTTPS but for some reason it is not detected automatically, enable this option in config.php. Please note that during the upgrade process, the $cfg['force_https'] = FALSE (disabled by default) setting will be added to the end of the config.php
  • Ability to add attributes to included JS/CSS files via the Resources class
  • Refactored and ordered icons and resources that use them
  • Detailed information about PHP installed on the server (phpinfo) has been added to the admin panel
  • Minor admin panel update
  • CKEditor updated to version 4.20.2
  • Fixed some missing lines in language files
  • 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.
  • Fixed some bugs.

 

Breaking changes:

New tags in system/admin/tpl/admin.tpl:

  • 'ADMIN_BREADCRUMBS' - contains bread crumbs
  • 'ADMIN_TITLE' - now, as it should be, contains a title.

system/admin/tpl/admin.structure.tpl:

  • 'ADMIN_STRUCTURE_UPDATE_DEL_URL' replaced with two new tags: 'ADMIN_STRUCTURE_DELETE_URL' and 'ADMIN_STRUCTURE_DELETE_CONFIRM_URL'
  • 'ADMIN_STRUCTURE_TPLMODE' replaced with 'ADMIN_STRUCTURE_TPL'

System core info was moved to its logical location (to Other/Infos) in admin panel. So there are new tags in system/admin/tpl/admin.infos.tpl:
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

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

File renamed: plugins/i18n/i18n.admin.extensions.phpplugins/i18n/i18n.extension.install.done.php

 

For more detailed info see:

 

Updating from previous versions

  • For updating from previous Siena version — see instructions here.
  • For upgrading from Genoa — see this document (you will also need files from cotonti-legacy to perform the upgrade).
]]>
Sun, 19 Mar 2023 10:20:00 -0000
Image slider in articles

Slideshow with thematic images in the article or in the full news without third-party plugins.
And so, an instruction, a guide, a master class, as anyone likes, on creating a slideshow in an article to illustrate content, emphasize its semantic load, form the aesthetics of the site using Out of the Box tools, without installing new extensions.

Experienced users and administrators of Cotonti sites, please do not swear - this manual is written for the most part for those who are just starting to learn Cotonti Siena.

What will we need?

1. Installed module "PFS".
Read about installation and configuration at the link.

2. Installed module "Page".

3. To know where in the admin panel Extra fields.

4. Be able to use some code editing programs, for example "Notepad++" and to access site files FTP manager - for example "FileZilla Client".

5. Connected toolkit library for creating interfaces - Bootstrap 5.3. compiled files (Compiled CSS and JS)

(If anyone does not know how to connect - create a separate topic on the forum).

Let's go


Extrafields.

We go into the extrafields of the "Page" module:
      Administration panel / Other / Extra fields / Table cot_pages - Pages module
or if it's easier for someone on the link:
https://Your_Project.com/admin.php?m=extrafields&n=cot_pages

* Your_Project.com - replace with your site's domain

 

                                  click on the picture to view in full size

We create three extrafields:

For each "field_type" or "Type of field" set - "input".
"HTML-code of the field" or "Base HTML" - we do not prescribe anything here, by default it is filled in automatically.

The first extrafield for the first picture.
For the first picture in the slideshow, write:
in "field_name" or "Name" - "head_screen_1"
in "field_description" or "Description(_TITLE)" - "Article Image #1"

The second extrafield for the second picture.
For the second picture in the slideshow, write:
in "field_name" or "Name" - "head_screen_2"
in "field_description" or "Description(_TITLE)" - "Article image #2"

The third extrafield for the third picture.
For the third image in the slideshow, write:
in "field_name" or "Name" - "head_screen_3"
in "field_description" or "Description(_TITLE)" - "Article Image #3"

Or like this, I think it will be more clear to show, fill in only two lines and control "Field type" - "input"

 

That's all for extrafields!


Moving on to our "Page" module templates,
they must be located in the appropriate folder of your frontend theme (skin), namely at:
"themes/yourtheme_folder/modules/page".

(we read about how to put them there correctly here, paragraph "Customization, that is, setting and changing the appearance of templates")

Open the template for adding page page.add.tpl
We find where the PFS module is registered in our template, this is {PAGEADD_FORM_PFS}.

 

It doesn’t matter if it is registered or not, we “put” the code on top of it, which is below:

!!! I draw your attention, all the code in this material requires the connected library "Bootstrap 5.3"

<!-- IF {PHP.cot_modules.pfs} -->
<!-- IF {PAGEADD_FORM_PFS} -->
<div class="list-group-item list-group-item-action pb-2 px-2 px-sm-2 px-lg-auto mb-3">
  <div class="input-group input-group-outline row">
	<div class="col-12 col-md-6">
	  <p>
		<span class="fs-6 text-muted">{PHP.L.Mypfs}</span>
	  </p>
	</div>
	<div class="col-12 col-md-6">
	  <div class="col-12 fs-6 text-dark float-end">{PAGEADD_FORM_PFS} </div>
	</div>
  </div>
<!-- IF {PAGEADD_FORM_HEAD_SCREEN_1} -->
<div class="input-group input-group-static row">
  <div class="col-12 col-md-4">
	<p>
	  <span class="fs-6 text-muted">{PAGEADD_FORM_HEAD_SCREEN_1_TITLE}<span class="text-danger"> {PHP.L.URL}</span>:</span> 
	</p>
  </div>
  <div class="col-12 col-md-8">
	<div class="input-group input-group-static mb-4"> {PAGEADD_FORM_HEAD_SCREEN_1}</div>
  </div>
</div>
<!-- ENDIF -->
<!-- IF {PAGEADD_FORM_HEAD_SCREEN_2} -->
<div class="input-group input-group-static row">
  <div class="col-12 col-md-4">
	<p>
	  <span class="fs-6 text-muted">{PAGEADD_FORM_HEAD_SCREEN_2_TITLE}<span class="text-danger"> {PHP.L.URL}</span>:</span> 
	</p>
  </div>
  <div class="col-12 col-md-8">
	<div class="input-group input-group-static mb-4"> {PAGEADD_FORM_HEAD_SCREEN_2}</div>
  </div>
</div>
<!-- ENDIF -->
<!-- IF {PAGEADD_FORM_HEAD_SCREEN_3} -->
<div class="input-group input-group-static row">
  <div class="col-12 col-md-4">
	<p>
	  <span class="fs-6 text-muted">{PAGEADD_FORM_HEAD_SCREEN_3_TITLE}<span class="text-danger"> {PHP.L.URL}</span>:</span> 
	</p>
  </div>
  <div class="col-12 col-md-8">
	<div class="input-group input-group-static mb-4"> {PAGEADD_FORM_HEAD_SCREEN_3}</div>
  </div>
</div>
</div>
<!-- ENDIF -->
<!-- ENDIF -->
<!-- ENDIF -->

 

 

We save our template for adding a page "page.add.tpl".
Now we create a page, a link to create a new page is usually on any page or article.
Or go directly to the link:
https://Your_Project.com/index.php?e=page&m=add

* Your_Project.com - replace with your site's domain

We fill in all the fields and go to the newly created fields for the pictures of our slider.
If everything is done correctly, you will see something like in the screenshot below.

 

 

Click on the link "My Files".
In the browser window that opens, create a new folder "Article with slider".

 

 

After creating a new folder, it will appear in the list at the top of the page.

 

 

Open the "Article with slider" folder and by clicking on the "Browse" button we load three pictures of the same size from the computer, for example, 640 by 420 pixels (px).

 

 

After clicking on the "Upload" button, and after uploading the pictures, we will find ourselves in the "Article with slider" folder, where we see three links to our pictures.
Copy these links as in the screenshot below.

 

 

We insert links into our created extrafields for pictures of the slideshow.
!!! But pay attention!
At this stage, inserting a link in each field, you need to remove the site address, including the slash ("/" sign), which is located immediately after the name of your site's domain zone - ru, com, net, ...
see screenshot below.

 

 

Now when all the fields of the page creation form are filled in and the links to the pictures of the slideshow are spelled out correctly, we press the "Publish" button.


Our new page has opened, but there is no image slider in the article....cool


Open the full news/article template "page.tpl",
which must be located in the folder of your theme (skin) of the frontend, namely at:
"themes/yourtheme_folder/modules/page"

Now in the right place, usually above the block with text, paste the code below:

 

<!-- IF {PHP.pag.page_head_screen_1} OR {PHP.pag.page_head_screen_2} OR {PHP.pag.page_head_screen_3} -->
<!-- the slider block is shown if at least one picture is attached -->
<div class="card-header p-0 mx-3 my-3 position-relative z-index-1">
  <div id="carouselExampleIndicators" class="carousel slide">
    <div class="carousel-indicators">
	<!-- IF {PAGE_HEAD_SCREEN_1} -->
	<!-- in case there are less than three pictures -->
      <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
	 <!-- ENDIF -->
	 <!-- IF {PAGE_HEAD_SCREEN_2} -->
	 <!-- in case there are less than three pictures -->
      <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1" aria-label="Slide 2"></button>
	  <!-- ENDIF -->
	  <!-- IF {PAGE_HEAD_SCREEN_3} -->
	  <!-- на случай, если картинок меньше трех -->
      <button type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2" aria-label="Slide 3"></button>
	  <!-- ENDIF -->
    </div>
    <div class="carousel-inner">
	<!-- IF {PAGE_HEAD_SCREEN_1} -->
	<!-- in case there are less than three pictures -->
      <div class="carousel-item active shadow ">
        <img src="https://www.cotonti.com/{PHP.cfg.mainurl}/{PAGE_HEAD_SCREEN_1}" class="d-block w-100 img-fluid border-radius-md" alt="{PAGE_SHORTTITLE}" loading="lazy">
      </div>
	  <!-- ENDIF -->
	  <!-- IF {PAGE_HEAD_SCREEN_2} -->
	  <!-- in case there are less than three pictures -->
      <div class="carousel-item">
        <img src="https://www.cotonti.com/{PHP.cfg.mainurl}/{PAGE_HEAD_SCREEN_2}" class="d-block w-100 img-fluid border-radius-md" alt="{PAGE_SHORTTITLE}" loading="lazy">
      </div>
	  <!-- ENDIF -->
	  <!-- IF {PAGE_HEAD_SCREEN_3} -->
	  <!-- in case there are less than three pictures -->
      <div class="carousel-item">
        <img src="https://www.cotonti.com/{PHP.cfg.mainurl}/{PAGE_HEAD_SCREEN_3}" class="d-block w-100 img-fluid border-radius-md" alt="{PAGE_SHORTTITLE}" loading="lazy">
      </div>
	  <!-- ENDIF -->
    </div>
    <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="prev">
      <span class="carousel-control-prev-icon" aria-hidden="true"></span>
      <span class="visually-hidden">Previous</span>
    </button>
    <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleIndicators" data-bs-slide="next">
      <span class="carousel-control-next-icon" aria-hidden="true"></span>
      <span class="visually-hidden">Next</span>
    </button>
  </div>
</div>
<!-- ENDIF -->

 

Save our full news/page template "page.tpl"

Now we reload our article / news, to which we added pictures for the slider.

If everything is done clearly according to the instructions, the result will be as in the screenshots below, and yet, for now, at the moment it can be seen in work here.

 

 

 

 

 

If you are using the UIkit3 library, slideshow documentation is here. If it does not work, write in this thread - I'll tell you.

After a little manipulation with the "header.tpl" template

    <meta property="og:locale" content="{PHP.lang}" />
    <meta property="og:type" content="article" />
    <meta property="og:title" content="{HEADER_TITLE}" />
    <meta property="og:description" content="{HEADER_META_DESCRIPTION}" />
    <meta property="og:url" content="{HEADER_CANONICAL_URL}" />
    <meta property="og:site_name" content="{PHP.cfg.maintitle}" />
	<!-- IF {PHP.env.ext} == 'page' AND {PHP.env.location} == 'pages' -->
	<meta property="og:image" content="{PHP.cfg.mainurl}/{PHP.pag.page_head_screen_1}" />
	<!-- ELSE -->
	<meta property="og:image" content="{PHP.cfg.mainurl}/apple-touch-icon.png}" />
	<!-- ENDIF -->
    <meta property="og:image:type" content="image/jpeg" />

we can achieve that when "sharing" this page in social networks and instant messengers, it would pull up the first picture of our news or article.

Like this in telegram

 

Like this in facebook

 

Like this in "VK"

 

Like this in "mail ru"

 

if it was useful and helped you, click "thank you" wink

I wish you successful and colorful projects, and take care of yourself! smiley

please forgive me for my english laugh

discuss on the forum

]]>
Sat, 04 Mar 2023 02:56:00 -0000
Cotonti Siena 0.9.21 About Siena

If you are a new to Cotonti — please read a brief info about this CMF and its requirements.

See detailed instructions for first-time install or updating guides.

 

Release info

Whats new:

  • Removed outdated 'news' plugin. Please use 'Index news' instead.
  • The CotDB class has been rewritten. We have taken the first step to using different databases, not just MySQL.
  • The cot_import_date() function can now accept string values. Date/time values ​​are allowed in any format that the strtotime() function supports. See: https://www.php.net/manual/en/datetime.formats.time.php This makes it easier to use different datepickers on the frontend.
  • Compatibility with PHP 8.1
  • Htmlpurifier updated to version 4.15.0
  • Improvements in 'i18n' plugin. (Support for multilingual content in core and extensions)
  • Several improvements and fixes

For more detailed info see:

Commits list

Closed 0.9.21 issues

 

Updating from previous versions

  • For updating from previous Siena version — see instructions here.
  • For upgrading from Genoa — see this document (you will also need files from cotonti-legacy to perform the upgrade).
]]>
Mon, 17 Oct 2022 06:34:00 -0000
Cotonti Siena 0.9.21 released Whats new:

  • Removed outdated 'News' plugin. Please use 'Index news' instead.
  • The CotDB class has been rewritten. We have taken the first step to using different databases, not just MySQL.
  • The cot_import_date() function can now accept string values. Date/time values ​​are allowed in any format that the strtotime() function supports. See: https://www.php.net/manual/en/datetime.formats.time.php. This makes it easier to use different datepickers on the frontend.
  • Compatibility with PHP 8.1
  • Htmlpurifier updated to version 4.15.0
  • Improvements in 'i18n' plugin. (Support for multilingual content in core and extensions)
  • Several improvements and fixes
  • Lots of fixes and improvements

For more detailed info see:

Commits list

Closed 0.9.21 issues

 

Learn more, download and upgrade

]]>
Mon, 17 Oct 2022 06:26:00 -0000
Files module Module for CMF Cotonti.    
    
The module organizes the management of attachments to pages, posts and any other objects, photo galleries creation for pages and posts. It also combines the users personal file storage, site file storage for site administrators, avatars and user albums management.
It is a replacement for the PFS module, the "User images" plugin included in the Cotonti "box" and the "Attach2" plugin.

GitHub: https://github.com/Alex300/files
Module page: https://lily-software.com/free-scripts/cotonti-files (russian)

 

Features

  • The ability to store files both in the local file system on the server and in remote file storages, such as Amazon AWS S3, Azure Blob Storage, Yandex Objet Storage, BunnyCdn, Google Cloud Storage, WebDAV, FTP, SFTP, etc.
  • Modern upload mechanism based on jQuery File Upload
  • Support for multiloading.
  • Dragging files with the mouse directly to the upload form.
  • Downloading files in parts ("Chunks") allows you to bypass the 2 MB file upload limit via $_POST.
  • Use both the GD library and ImageMagick for image processing. The last one supports a larger number of image formats, incl. HEIC/HEIF, which are used in Apple iPhone smartphones.
  • Downscale large images to the specified size when uploading.
  • Using watermark for images.
  • Simple integration via function callback from a template.
  • Downloads are counted and occur with the original file name.
  • Create images for preview (thumbnail) and easily configure it.
  • Extrafields support.
  • Special BBCodes for inserting images and galleries into the text of pages, regardless of the selected parser.
  • Supporting image formats by the GD library: .avif, .bmp, .gif, .jpg, .png, .tga, .tpic, .wbmp, .webp, .xbm
  • Supporting image formats by the Imagick library.

 

System requirements and limitations

  • Installed Cotonti Siena version not lower than 0.9.24 beta. (Files v. 1.0.8 is compatible with Cotonti Siena 0.9.18)
  • PHP version 7.4 and higher. (Files v. 1.0.8 is compatible with PHP v 5.4)
     .bmp is supported by GD library on PHP >= 7.2,
     .tga is supported by GD library on PHP >= 7.4, thumbnails creating in JPEG
     .avif is supported by GD library on PHP >= 8.1
  • To use remote file storage, Flysystem and the appropriate adapter must be installed
  • jQuery File Upload shows preview on image uploading not for all image formats.
  • Cotonti Lib library version 2.2.x installed on your site.
  • The module is not compatible with the PFS module and the "User images" plugin. They should not be installed if you are going to use the "Files" module.
  • Templates "in a box" are designed to use a theme implemented on the Bootstrap v3 framework (Installed separately)

Note. Due to the different database structure and the way files are stored, the "Files" module will not automatically pick up files present on the site from the "PFS" module and the "User images" and "Attach2" plugins.

 

Data transfer from the "PFS" module and the "User images" and "Attach2" plugins.

If you want to use the "Files" module for an existing site, you should use a converter to transfer data between modules. You can order it here. At the moment, there is a converter for transferring data from these three extensions, because they are one of the most frequently used. But you can make a converter for any other module or plugin.

 

Installation

  • Download the archive and unpack it into the folder with the modules of your site.
  • In the "Administration panel > Extensions" menu, install it by clicking "install" button.
  • In the module settings, select the settings that suit you.
  • In the control panel templates "admin.users.tpl" and "admin.users.tpl" and also in some others, create tags in accordance with the recommendations on the module page in the control panel. (https://<your_domain>/admin/extensions?a=details&mod=files)
  • If necessary, on the user group editing page, set limits on the size of the uploaded file, the total user file space and the maximum number of attachments per object. Each user group can have its own permissions.
  • Note that the sizes are specified in bytes, '0' means "unlimited", and '-1' means prohibition.
  • Create a directory for files on your server ("datas/files" is used by default) and set write permissions for PHP (for example, CHMOD 775 or CHMOD 777).
  • Use Resources::setAlias() in your theme to declare aliases for Bootstrap files if you plan to use it and it is installed in a folder, different from the one in the Resources class.

 

Version history

v. 2.0.1

  • Compatible with Cotonti 0.9.25

v. 2.0.0

  • Use the Image bundle from the Cotonti Lib for image processing.
  • Use the File System from the Cotonti Lib and Flysystem to store files and operate with them.
  • File names obfuscation.
  • Downscale uploading images in browser, if possible.
  • Code refactoring. The functions have been renamed using the pattern cot_filesFunctionName().

v. 1.0.8

  • Added support for deleting users, pages and forum posts to the trash. When deleting these items, the files are not deleted and after restoring the item from the trash, the files remain attached to these elements. When deleting items from the trash, the related files are deleting too.

v 1.0.7

  • Added support for image formats: avif, bmp, gd2, gd, tga, tpic, wbmp, webp, xbm
  • jQuery File Upload updated to version 10.32.0
  • Compatibility with PHP 8.1
  • Fixed some bugs

 

Read more about usage (russian)

If you can't read russian, please feel free to ask me and I'll try to translate documentation to English.

Contact

Please use the Extensions forum to discuss plugin features and GitHub tracker to submit bug reports.

 

]]>
Tue, 16 Aug 2022 05:27:00 -0000