Our goal in creating this framework was to make Horuph as modular as possible. These modules are connected via APIs.
Horuph is a web development framework that is based on pure PHP, JavaScript and HTML. It's super light weight and very easy to develop.
Horuph's beauty in development is the extreme modularity of its code. All the modules are made, tested and refactored as complete independent parts. The idea of building addons is to add building blocks to the horuph core instead of dependent puzzle pieces.
To be able to use all the powers that Horuph framework gives you need to only be familiar with HTML, JQuery or JavaScript and PHP. here are the collection of the cheatsheets that could help you in the process of the development with Horuph studio.
Horuph Studio framework needs a server that can run PHP codes, so you need to install the server of your choice and also make php available on that server to start running Horuph Studio framework.
You only need minimum PHP version 7.1.3 to start developing.
You'll need to restart Apache server after these.
Uncomment this line:
LoadModule rewrite_module modules/mod_rewrite.so
Search for these two lines and change your root to your project folder:
DocumentRoot "${SRVROOT}/htdocs/www"
<Directory "${SRVROOT}/htdocs/www">
Change the AllowOverride to All:
#AllowOverride None
AllowOverride All
Change the index file extension:
#DirectoryIndex index.html
DirectoryIndex index.php
Uncomment these lines:
extension=sqlite3
extension=sockets
extension=curl
extension=mbstring
extension=gd2
extension=openssl
Karen is the command line tool for Horuph.
Download the appropriate version of Karen for your operating system.
Follow the instructions to install Karen on your system.
You can easily install Horuph with Karen. You can follow the instructions provided to install the Horuph SDK.
In order to read and make changes to database files, you'll need 777 permission.
To activate the rewrite rules on nginx servers please change the location value like the example:
location / { try_files $uri $uri/ /index.php?$args; }
Here you can learn basic understandings of horuph framework folders.
bin directory: This directory holds the server files.
core directory:Addons are the building blocks of Horuph. Every functionality and feature is an Addon which is completely independent from the core. You can use the addons already made for Horuph and develop your own addons if you wish.
Making an addon is as easy as making a folder with the name of your addon inside the core/addons directory. We will explore more in this help documentation.
The first thing you need to develop our addon, is a manifest.json file. This file is the identification for your addon. It is a JSON formatted file that has properties as below:
title: This field contains the name of your addon. You can either write the name directly or use a token from your addon's language pack.
version: This is a string value containing the version number of your addon.
priority: 0Your addon is displayed on the lower row.
priority: 1Your addon is displayed on the upper row.
title This field contains the name of your addon button. You can either write the name directly or use a token from your addon's language pack.
icon This key has a string value referencing Material Icons.
iconfilter This key has a string value referencing Material Icons. This is used when you want to overlap two icons as your addon icon in the toolbar.
click This key has a string value referencing the JavaStript function name that acts on this button's click. This function must be placed inside the core/addons/[ADDON_NAME]/scripts/staff.phtml script.
{
"title": "addon_title",
"version": "1.0",
"priority": 1,
"toolbar": {
"title": "addon_action_name",
"icon": "addon_icon",
"iconfilter": "",
"click": "DoSomething"
}
}
Addon's manifest.json example located inside core/addons/[ADDON_NAME]:
This is where you add an icon for your addon. You'll need to add your icon with these formats and names inside your addon folder:
To keep a documentation on the latest changes of your addon, you'll need to make a version folder inside your addon folder. This folder contains html files with the name of your language packs; for example fa.html
You need to have a publish JSON for your addon. This JSON contains information about your addon that will be used in the publishing process.
You will also specify the requirements of your addon inside this JSON file.
description: This field contains the description of your addon. You can either write the description directly or use a token from your addon's language pack.
developer: This is a string value containing the name of the addon's developer.
url: This is a string value containing your website or email.
requirements: This is an array to specify the addon's that are required to use your own addon.
If you do not use any addons in your code, you can remove this field from your JSON.
addon This is a string value containing the name of the addon you require.
version This is a string value containing the version of the addon you require.
{
"description":"publish_desc",
"developer":"John Doe",
"url":"http://www.horuph.com",
"requirements":[
{"addon":"cartable", "version":"1.2.100"},
{"addon":"users", "version":"1.1.230"}
]
}
Addon's publish.json example located inside core/addons/[ADDON_NAME]:
Horuph addons have a structure that you can implement according your requirements. Here we will explore the addon structure and what you need to implement your own addons.
Horuph is easily implementable with different language packs. You only need to create a json file with the name of your language inside the languages folder of your addon.
{
"addon_name": "نام افزونه"
}
fa.json example located inside core/addons/[ADDON_NAME]/languages:
default.phtml: If you add this file inside your public folder, every variable, method and class that is written inside this file will be available throughout the application.
All the pages in your addon that can be shown in the site, are located here.
To start using pages, first you will need to make a directory in your addon folder, named pages.
To enable indexing your pages and to identify them, you need to add a file named _index.phtml inside your pages folder.
This file contains a JSON that lists your pages. Here are the values listed in the file:
titleThis field contains the name of your page. You can either write the name directly or use a token from your addon's language pack.
pageThis field points to the name of the page file in your pages directory.
linkableThis field specifies whether or not your page can be added by other addons. The value is specified by 0 or 1.
{
"pages": [
{
"title": "page_title",
"page": "default",
"linkable": 1
}
]
}
You should handle these meta values in this file according to the page that is displayed. All the meta data for your pages is handled in this file.
You can access the page's token with $_data. This value is set by the page value set in your pages _index.phtml file.
The next step is to add meta data for your pages. If you don't add this data, you will get a 404 error. To add meta data, add a _meta.phtml file inside your pages folder.
Here is an example of the _index.phtml file located in core/addons/[ADDON_NAME]/pages/:
This file must return a JSON file with these values:
{
"title": "YOUR_PAGE_TITLE",
"description": "YOUR_PAGE_DESCRIPTION",
"image": "YOUR_PAGE_THUMBNAIL_IMAGE",
"status": YOUR_PAGE_STATUS,
"canonical": "YOUR_PAGE_CANONICAL_URL",
"template": "YOUR_PAGE_TEMPLATE"
}
You should handle these meta values in this file according to the page that is displayed. All the meta data for your pages is handled in this file.
You can access the page's token with $_data. This value is set by the page value set in your pages _index.phtml file. $_data for default page can be empty.
You can have a custom console for your addon to manage. Your console can have multiple tabs that manage different tasks.
To have a console for your addon, first you need to make a directory named console inside core/addons/[ADDON_NAME] directory.
Then in this console directory, you need to make a file named _index.phtml. This file contains a JSON that specifies your console's tabs.
_index.phtml example located inside core/addons/[ADDON_NAME]/console:
title This field is the name of the console tab. You can use a string token from your language pack.
page This is a string value indicating the name of the page that contains this tab. This page must be located inside the console tab next to the _index file.
count This value is optional inside the JSON. It uses a string value indicating the name of the page that controls the alert counter for this tab. This page must be located inside the console tab next to the _index file and it should return a number.
{
"tabs": [
{
"title": "categories",
"page": "categories",
count: "categories_counter"
}
]
}
If you need settings to apply to your addon, you can use the settings implementation of Horuph.
To have settings for your addon, create a file named settings.phtml inside your addon's console directory.
Add this settings tab inside your console's _index.phtml file.
Inside this settings file, you should create a form to give the user the ability to change the settings.
Inside your console's action file, handle the settings form with the act of "config".
You should save your settings inside your addon's config file, inside your addon's data.
addonsettingitem=1
Here is an example of the config.ini file located inside data/addons/[ADDON_NAME]/:
Create a folder named styles inside your addon's directory.
Inside this folder, there are multiple types of styles that you can create:
default.phtml: The styles you put in this file are only accessible to the pages of your own addon and other addon's can't use them.
global.phtml: The styles you put in this file are accessible to all the addons.
console.phtml: The styles you put in this file affect only the console of your addon.
global_console.phtml: The styles you put in this file affect all the consoles.
print.phtml: The styles you put in this file affect the print styles of the site.
Create a folder named scripts inside your addon's directory.
Inside this folder, there are multiple types of scripts that you can create:
default.phtml The scripts you put in this file are only accessible to the pages of your own addon and other addon's can't use them.
global.phtml The scripts you put in this file are accessible to all the addons.
console.phtml The scripts you put in this file affect only the console of your addon.
global_console.phtml The scripts you put in this file affect all the consoles.
staff.phtml The scripts you put in this file are only available to the staff of the site.
All your AJAX pages are placed in this directory.
You can create up to one level of sub directories to better organize your AJAX pages.
These AJAX pages are accessible from [HOME_URL]/ajax/[ADDON_NAME]/[YOUR_AJAX_PAGE]
To create webparts for your addon, first create a folder insode your addon's directory named webparts.
To index your webparts, you'll need a _index.phtml file inside your webparts directory.
This file contains a JSON that lists your webparts. Here are the values listed in the file:
title This field contains the name of your webpart. You can either write the name directly or use a token from your addon's language pack.
page This field points to the name of the webpart file in your webparts directory.
{
"webparts": [
{
"title": "webpart_title",
"page": "webpart_page"
}
]
}
Here is an example of the _index.phtml file located in core/addons/[ADDON_NAME]/webparts/:
Creating APIs in Horuph is very easy and straight forward.
All you need to do is create a folder inside your addon's directory with the name of "api".
Next step is to create your API files inside this directory and they all will have the appropriate headers for acting as an API.
Your databases for your addon must be placed inside a directory with the name of your addon inside the data directory.
This is the directory map that should contain your data: data/addons/[ADDON_NAME].
Here you can learn what horuph have has to offer you in scripts.
These variables are automatically generated and ready to use:
Variable | Description |
---|---|
maxboxheight | This variable contains an integer value that has the best height for a popup window. |
currenttime | This variable contains the current system time. |
These methods are accessible to everyone:
This method is for creating an AJAX popup window.
Each window has an id that gets generated with this method.
Then you post to a page containing your AJAX page as explained in the Addon AJAX directions.
If you have any values to post you can use id, item, content or query to send your data.
Then you set the html of the box created in the first step with the data fetched from your post method.
This method takes three variables:
Variable | Description |
---|---|
windowWidth | This takes a number value as pixels for the box width. |
windowTitle | This takes a string value for the title that is shown on top of the box. |
windowToken | This takes a string value that is used to seperate each opened window from the other. |
Here is an example of creating a window box:
function openPopupWindow(itemId) {
var windowboxid = openWindowBox(500, 'windowTitle', 'windowToken');
$.post('[HOME_URL]/ajax/[ADDON_NAME]/[AJAX_PAGE]', {
item: itemId
}, function (data) {
$('#' + windowboxid + 'holder').html(data);
});
}
This method is for openning a popup window that is for asking a yes or no consent.
This method posts the yes action to your action.phtml page with the windowAction you specified.
If you have any values to send for your action, you can use id, item, content or query.
This method uses these variables:
Variable | Description |
---|---|
windowAction | This is a string to identify the action used is your action.phtml page. |
windowTitle | This takes a string value for the title that is shown on top of the box. |
addonName | This arguments takes your addon name as string. |
windowWarning | You can use this last argument to add a warning message under the box title. This value can be an empty string too. |
Here is an example of a yes or no dialog with post action:
function openYesNoDialog(item) {
var windowboxid = openConfirmBox('boxAction', 'boxTitle', 'addonName', 'extraText');
document.getElementById(windowboxid + '_item').value = item;
}
This method is for openning a popup window that is for asking a yes or no consent.
This method handles the yes action with the script you pass with the arguments.
If you have any values to send for your action, you can use id, item, content or query.
This method uses these variables:
Variable | Description |
---|---|
windowAction | This is a string to identify the action used is your action.phtml page. |
windowTitle | This takes a string value for the title that is shown on top of the box. |
addonName | This arguments takes your addon name as string. |
windowWarning | You can use this last argument to add a warning message under the box title. This value can be an empty string too. |
actionScript | This argument takes the script of your window action as a string value. |
Here is an example of a yes or no dialog with script action:
function openYesNoDialogWithScript(item) {
var windowboxid = openConfirmBoxScript('boxAction', 'boxTitle', 'addonName', 'extraText', 'DoSomething();');
document.getElementById(windowboxid + '_item').value = item;
}
function DoSomething() {
//handle your action here
}
Here you can learn what horuph have has to offer you in scripts.
There are some variables in Horuph that are filled automatically and they are accessible throughout the application.
Variable | Description |
---|---|
$homeUrl | This variable returns your home url which is set from horuph.ini file. |
$langShort | This variable gives you the current language with the short format like "fa". |
$ipaddress | This variable returns the IP address of the user. |
$userID | This variable returns the user id. If user has not logged in, this variable is empty. |
You can use the $userActions object to access the user data inside your project.
Here are the methods available in this object to access the user:
This method will return the user's object that contains all the information of the user.
You can access the user's information like this:
$userActions->userByID($userid)->userName;
$userActions->userByID($userid)->fullName;
$userActions->userByID($userid)->userMail;
$userActions->userByID($userid)->userCell;
$userActions->userByID($userid)->userImage;
$userActions->userByID($userid)->userToken;
This method will return the user's object that contains all the information of the user.
You can access the user's information like this:
$userActions->userByToken($token)->userID;
$userActions->userByToken($token)->userName;
$userActions->userByToken($token)->fullName;
$userActions->userByToken($token)->userMail;
$userActions->userByToken($token)->userCell;
$userActions->userByToken($token)->userImage;
This method will return the user's object that contains all the information of the user.
You can access the user's information like this:
$userActions->userByMail($mail)->userID;
$userActions->userByMail($mail)->userName;
$userActions->userByMail($mail)->fullName;
$userActions->userByMail($mail)->userCell;
$userActions->userByMail($mail)->userImage;
$userActions->userByMail($mail)->userToken;
These variables get set automatically if passed by either query or forms.
These variables are used to pass data through out the application.
These methods are made to ease your programming.
This method can access your language pack's texts with your token.
This method uses three variables:
Variable | Description |
---|---|
language_identifier | This takes a short formated language id. You can mostly pass $langShort |
addon_name | This takes a string that is your addon's name. |
string_token | This takes a string that identifies the string used in your language file. |
This method generates a url string with all the data that needs to get passed through query. We use this method for calling urls in order to accommodate all the urls reffering to this page, while using url mapping techniques.
This method uses these variables:
Variable | Description |
---|---|
language_identifier | This takes a short formated language id. You can mostly pass $langShort |
addon_name | This takes a string that is your addon's name. |
data | This takes a string that is usually the page name. Pass an empty string if you are reffering to your public page. |
id | This takes an integer value. This argument corresponds to the $_id variable used through out the application. |
item | This takes an integer value. This argument corresponds to the $_item variable used through out the application. |
content | This takes a string value. This argument corresponds to the $_content variable used through out the application. |
query | This takes a string value. This argument corresponds to the $_query variable used through out the application. |
alert |
This argument takes a string value to identify an alert for the page. If you set this argument with a non empty string, you can use it to identify the result of an action taken. Some values are set by default that show a toast message to the user according to the alert message, like add, edit, delete, err. |
page | This argument takes an integer value to identify the page number for pagination. You can set it to 0 or 1 for default. |
This method creates input field for image upload and shows a preview of the uploaded image instead of the input field.
This method uses three variables:
Variable | Description |
---|---|
addonName | This takes a string that is your addon's name. |
inputName | This is the name of the input that uploads the file. |
previousValue | This argument is the previous upload location of the file. Pass an empty string variable if there was no image uploaded previously. |
This method uploads file to server.
This method uses three variables:
Variable | Description |
---|---|
inputName | This is the name of the input that uploads the file. |
folderName | This argument points to the location you want to upload your files. The first firectory you need to write is your addon's name. |
fileType | This argument takes a string value containing the type of the file you want to upload, like image. |
This method limit the string you give to the length that you specify.
This method uses these variables:
Variable | Description |
---|---|
text | This is the string that needs limitation. |
length | This is an integer of the number of characters to limit the string. |
This method makes redirecting pages easy.
Variable | Description |
---|---|
url | This takes a string value for the url. We recommand using URLGenerator to pass the address. |
This method redirects to the current page with a specified alert.
Variable | Description |
---|---|
alert |
This argument takes a string value to identify an alert for the page. If you set this argument with a non empty string, you can use it to identify the result of an action taken. Some values are set by default that show a toast message to the user according to the alert message, like add, edit, delete, err. |
This method is makes database transaction easy if you are using SQLite database.
This method uses these variables:
Variable | Description |
---|---|
query | This argument gets a string that should be executed by your SQLite database. |
database_location | This argument takes a string, pointing to your database file. |
Here you can learn what horuph have has to offer you in scripts.
This addon is for managing your cartable. You don't need to code extra pages for your console to manage your cartable anymore. Implementing this addon will do the job easily.
Here are the steps you need to work with this addon:
Navigate to your horuph directory in your terminal and write this command:
karen install --addon gearback/cartable
You can add this dependency with the addon manager in your site:
Create a folder inside your addon's console in core, named "cartable".
Add a file named _index.phtml in this cartable directroy.
This file should contain a JSON formatted text to identify your cartable pages.
The fields of this JSON are listed here:
page This field contains the name of the page that must be shown for each cartable item. This page is located inside your console's cartable directory, inside a folder named forms.
The final location of this page is: core/addons/[ADDON NAME]/console/cartable/forms/[PAGE].phtml
title This field contains the name of your cartable.
description This field contains the description for your cartable.
user_related This field contains either 0 or 1. Pass a value of 1 if you want to show the user that submitted this cartable item on top.
alert This field contains a dynamically produced integer to show the count of cartable items that need verification.
database This object contains information on your database and the query to show the cartable items.
Here are listed the information for this field:
type This field contains the type of your database file, like sqlserver, sqlite or mysql.
name This field contains the name of your database file that is located inside your addon's data directory.
auth You only need to add this field if you are using SQL Server.
This field contains auth array of your SQL server authentication.
It is recommended to keep your authentication array in a PHP variable inside your addon's public folder, in default.phtml.
queries In this field you'll need to specify the queries that the addon needs to list and search your database for data that needs verification.
For the search query, use [searchquery] for finding the result.
Here is an example of the _index.phtml file located in core/addons/[ADDON NAME]/console/cartable/:
{
"cartables": [
{
"page": "cartable_page",
"title": "cartable_page_title",
"description": "cartable_page_description",
"user_related": 1,
"database": {
"type": "sqlserver",
"name": "db.db3",
"auth": <?php echo(json_encode($db_auth_array)); ?>,
"queries": {
"list": "SELECT ID,name FROM table_name WHERE isvalid = 0 ORDER BY ID",
"search": "SELECT ID,name FROM table_name WHERE (name || desc) LIKE [searchquery] ORDER BY ID"
}
},
"alert": <?php echo(ReadFirstRecordByConnectionString("SELECT COUNT(*) FROM table_name WHERE isvalid = 0", "addons/addon_name/db.db3")); ?>
}
]
}
This addon is for managing your reports. You don't need to code extra pages for the report function throughout you application anymore. Implementing this addon will do the job easily.
Here are the steps you need to work with this addon:
Navigate to your horuph directory in your terminal and write this command:
karen install --addon gearback/reports
You can add this dependency with the addon manager in your site:
Create a folder inside your addon's console in core, named "reports".
Add a file named _index.phtml in this reports directroy.
This file should contain a JSON formatted text to identify your report items.
The fields of this JSON are listed here:
form This field contains the name of the form that must be shown for each report item. This page is located inside your console's reports directory, inside a folder named forms.
The final location of this page is: core/addons/[ADDON NAME]/console/reports/forms/[PAGE].phtml
warning This field contains either false or true. Pass a value of false if you don't want to send waring to the reported user.
callquery This field contains a string value that is the query to show the reported item. This item is reachable with a token name [appparameter].
calldb This field contains the type of your database file, like sqlserver, sqlite or mysql.
Here is an example of the _index.phtml file located in core/addons/[ADDON NAME]/console/reports/:
{
"reports": [
{ "form": "reportFormName", "warning": ture, "callquery": "SELECT name FROM table_name WHERE token = '[appparameter]'", "calldb": "sqlite" }
]
}
Next, navigate to your site and open addons by clicking on apps in the administeration toolbar.
Click on the reports console.
You will see a list of the report types you created in the previous step.
Click on report options to add and edit the report details for your data.
Where ever you may need a report button for your data, you can use it like this example:
<a class="hrphreportbt" data-parameter="<?php echo($_content); ?>" data-app="addon_name" data-report="report_form" data-title="report_title">Report</a>
Here are the data used in this report button:
Variable | Description |
---|---|
data-parameter | This is the token for the data that you are adding the report button. This will be used to identify the data which was reported and used as [appparameter]. |
data-app | This field must be replaced by your addon's name. |
data-report | This is the form name you wrote in the _index.phtml file and created a file with this name inside core/addons/[ADDON NAME]/console/reports/forms/ |
data-title | This is the title of the report window. |
Here you can learn what horuph have has to offer you in scripts.
This is an example of using Horuph tools to create required inputs in your forms:
Each input that is required in your form must have a class named req-min.
The next and only step to make handle these necessary inputs, is to call validateForm method in the script of your page that checks the required inputs on the submit button click.
Here is an example of an HTML page containing a form with required fields:
<form class="form" id="formId" method="POST">
<div class="he-table he-w-100">
<div class="he-row">
<div class="he-cell-text"><?php echo(GetPackText($langShort, "title")); ?>:</div>
<div class="he-cell-input">
<input name="name" type="text" class="he-w-100 req-min" minlength="3" maxlength="100">
</div>
</div>
<div class="he-row">
<div class="he-cell-text"><?php echo(GetPackText($langShort, "question", "featurerating")); ?>:</div>
<div class="he-cell-input">
<input name="address" type="text" class="he-w-100 req-min" minlength="3" maxlength="200">
</div>
</div>
</div>
<div class="he-form-buttons">
<input id="formSubmitBtn" type="submit" value="Submit" class="he-button" />
</div>
</form>
<script type="text/javascript">$(function () { validateForm('formId', 'formSubmitBtn'); });</script>
* Please make sure that you specify minlength and maxlength in your input tag.
These are the variables used in this example that you need to change according to your addon:
Variable | Description |
---|---|
[INPUT_NAME] | This is the input name you choose for your code, for example userImage. Replace this [INPUT_NAME] every where with your own input name. |
$uploadedImage | This PHP variable points to the variable that holds the previously uploaded image's location. |
$homeUrl | This variable holds the url of your site. It is explaned in the PHP Helpers section. |
[ADDON_NAME] | This field must be replaced by your addon's name. |
This is the class used for identifying the required inputs:
Class name | Description |
---|---|
.req-min | By adding this class to your form's inputs, you define them as required and they cannot be left empty for submitting. |
This is the method used for validating the form on submit:
This method takes these variables:
Variable | Description |
---|---|
formId | This is the id of the form that needs validation. |
formSubmitButtonId | This is the id of the submit button inside the form that starts the validation process. |
This is a complete example of how to upload images with the help of horuph functions.
All you need to do is call a PHP method that will create the file input and handle the preview of the uploaded image.
These methods will automatically manage your upload process.
This process consists of uploading the image to server, showing the image thumbnail if previously uploaded instead of the upload button and a remove button next to the thumbnail image to remove the uploaded image.
First you need to choose a name for your input type file.
Then you need a PHP variable that points to the uploaded image location. This variable is empty in case there was no image uploaded previously.
Just call the FileUploadReady method to prepare your input and preview handling.
The last step is to upload the image to server using FileUpload method in your submit action.
Here is an example of file upload HTML structure:
//your html file
<div class="he-row">
<div class="he-cell-text">Icon:</div>
<div class="he-cell-input">
<?php FileUploadReady("addonName", "appicon", $appicon); ?>
</div>
</div>
//your server side
$appicon = FileUpload("appicon", "addonName", "image");
Horuph has a wonderful tool for resizing and cropping images that makes your coding easier and faster.
To resize your image, all you need to do is use this URL structure with your uploaded image location:
[homeUrl] / img / [maxWidth]X[maxHeight]_[resizeType] / [addon][imagePath]
Here are the variables that need to change:
Variable | Description |
---|---|
[homeUrl] | This is the home URL of your site. You can use $homeUrl fro the site variables for this field. |
[maxWidth] | This is the maximum width that you want your image to be resized. |
[maxHeight] | This is the maximum height that you want your image to be resized. |
[resizeType] | This is the type of the resize that you want to be applied to your image. |
[addon] | This is your addon's name. |
[imagePath] | This is the path of your uploaded image. |
Here is an example of a URL to resize the image:
<img src="<?php echo($homeUrl); ?>/img/100x100_crop/addonName/<?php echo($imagePath); ?>">
In Horuph everything works together and some addons might require some other addons and even a minimum version of that addon.
For the best practice, we recommend using this structure for your addon versioning.
By using this format, Horuph can better handle your updates and requirements.
An example for the prefered addon versioning is 2.5.100
Addon versioning in Horuph consists of three parts. Here is the structure:
Version number The version number can be any number you desire.
Sub version number The sub version number must be a one digit number.
We encourage developers to develop all their dreams with the tools that Horuph provides and publish them to grow the Horuph community.
Publishing your addons is very easy and is done in only a few steps.
Packing your addon is done via karen in your terminal.
You can see the command to pack your addon in the Karen's Pack Tutorial.
After you pack your extension, open the zip file that was extracted.
There is a languages folder inside your addon's directory in the packed folder.
Inside this languages folder, there are two automatically generated JSONs for Farsi and English that contain the publishing details for your addon.
If you need to change these texts or add more languages for your publishing details, you can do it here.
In the same folder as your languages, there is another folder named terms in your addon's packed folder.
Inside this terms folder, there are two automatically generated HTML files for Farsi and English that contain the terms of publishing for your addon.
If you need to change these html files or add more languages for your publishing terms, you can do it here.
Horuph Framework designed and created by Ali Pournasseh.
Latest version for Horuph Studio is v21.9.132 that you can download from here.