The Package Class
In Jalno, the packages\base\Package class is defined for managing and working with a project's packages. This class is used when working with files—to access a file within a package, get a file's path, and so on.
The following methods are defined in the Package class:
| Method | Purpose |
|---|---|
fromName(string $name): Package | Get a package |
getName(): string | Get the name of the parent package |
getFilePath(string $file): string | Get a file's path |
url(string $file, bool $absolute): string | Get a file's URL |
getFile(string $path): File\Local | Get a file |
getHome(): Directory | Get the package's details as an object of the Directory class |
getFileContents(string $file): string | Read a file's contents |
getOption(string $name): ?mixed | Get an option defined for the package |
setOption(string $name, mixed $value) | Add a new option for the package |
bootup() | Call the bootstrap file if it is configured in the package This method is called by the framework when packages are loaded. |
The framework uses the following getter and setter methods to complete the package information.
| Method | Purpose |
|---|---|
addDependency(string $dependency) | Add a dependency package |
getDependencies(): array | Get the names of the dependency packages |
addFrontend(string $source) | Add a frontend source |
getFrontends(): array | Get the frontend sources registered for the package |
setBootstrap(string $bootstrap) | Set the bootstrap file |
setRouting(string $routing) | Set the routing file |
getRouting(): ?File | Get the routing file |
getRoutingRules(): array | Get the routes defined in the routing.json file |
getConfigFile(): File | Get the package's configuration file (package.json) |
Accessing a Package
In the packages\base\Package class, the fromName method is defined for accessing a project's packages.
In addition to fromName, you can also access a project's packages by calling the package method defined in the packages\base\Packages class. For convenience, both fromName and package are defined as static methods.
If the specified package exists, the return value of fromName and package is an object of the packages\base\Package class that contains the package's details—such as its dependencies, routing file, and translation files—and, in general, all the settings configured in the package structure file (package.json).
If the specified package does not exist, a packages\base\IO\NotFoundException exception is thrown.
Accessing a package via the package method:
use packages\base\Packages;
$package = Packages::package("packagename");
Accessing a package via the fromName method:
use packages\base\Package;
$package = Package::fromName("packagename");
File Paths and URLs
Two methods, getFilePath and url, are defined for accessing file addresses.
Both methods take the file's path and name as a string input.
The specified file does not need to exist.
If the second argument of the url method is set to true, it returns the full address (as a URL).
The default value of this argument is false.
Difference between getFilePath and url
The getFilePath method is used to get a file's path inside the package, while the url method is used to get the file's internet (web) address.
Example 1:
<?php
namespace packages\packagename\controllers;
use themes\themename\views;
use packages\base\{Controller, Response, View, Packages, IO\File};
class Albums extends Controller {
public function insertImg(): Response {
$view = view::byName(views\Albums\InsertImg::class);
$this->response->setView($view);
if (Http::is_post()){
$inputs = $this->checkinputs([
'img' =>[
'type' => 'image',
"max-size" => 2097152, // Byte
"obj" => true,
"extension" => array('jpeg', 'jpg')
]
]);
$path = 'storage/public/albums/' . $inputs['img']->getFile()->md5() . '.' . $inputs['img']->getExtension();
$img = new File\Local(Packages::package('packagename')->getFilePath($path));
/**
* Or
* $img = Packages::package('packagename')->getFile($path);
*/
$directory = $img->getDirectory();
if (!$directory->exists()) {
$directory->make(true);
}
$inputs['img']->copyTo($img);
}
$this->response->setStatus(true);
return $this->response;
}
}
In the example above, we first build the file's storage path in $path, then pass $path to the getFilePath method so that the exact file path for the desired package is generated.
The output of the getFilePath method is as follows:
packages/packagename/storage/public/albums/0bc27259aae45199b214898a48d0a7bf.jpg
For more information about files and directories, refer to the Files and Directories pages.
Example 2:
<?php
namespace packages\packagename\controllers;
use packages\base\{Controller, Response, Packages, NotFound, ResponseFile};
class Albums extends Controller {
public function download($data): Response {
$file = Packages::package('packagename')->getFile($data["path"]);
if (!$file->exists()) {
throw new NotFound();
}
$responsefile = new ResponseFile();
$responsefile->setLocation(Packages::package('packagename')->getFilePath($file->path));
$responsefile->setSize($file->size);
$responsefile->setName($file->name);
$this->response->setFile($responsefile);
$this->response->setStatus(true);
return $this->response;
}
}
In the example above, we intend to give the user a file to download. First, we obtain an object of the File class corresponding to the received path and check whether the file exists.
For more information, refer to the Response page.
Example 3: Using the url method in a theme
<?php
namespace themes\themename\views\profile;
use packages\packagename\User as Model;
use packages\base\{Packages, frontend\Theme, views\Form};
use themes\clipone\{ViewTrait, views\FormTrait, views\TabTrait}; // Clipone is userpanel package theme name
class edit extends Form {
use ViewTrait, FormTrait, TabTrait;
protected $user;
public function __beforeLoad(){
$this->setTitle(t('profile.edit'));
$this->addBodyClass('profile');
$this->addBodyClass('profile_edit');
}
protected function getAvatarURL(): string {
if ($this->user->avatar_path) {
return Packages::package('userpanel')->url($this->user->avatar_path);
}
return Theme::url('assets/images/defaultavatar.jpg');
}
public function setUser(Model $user) {
$this->user = $user;
}
}
<div class="img-profile">
<img class="img-responsive img-circle" src="<?php echo $this->getAvatarURL(); ?>">
<h4 class="user-name">
<i class="fa fa-user"></i>
<?php echo $this->user->name; ?>
</h4>
</div>
Reading File Contents
The getFileContents method is defined for reading a file's contents.
This method takes the path and name of a file within the package as a string argument. If the file does not exist, a packages\base\IO\NotFoundException exception is thrown.
Example:
<?php
namespace packages\packagename\controllers;
use themes\themename\views;
use packages\base\{View, Controller, Packages, view\Error};
class Main extends Controller {
public function description() {
$view = view::byName(views\main\Description::class);
$this->response->setView($view);
try {
$description = Packages::package('packagename')->getFileContents("storage/public/description.txt");
$view->setData($description, 'description');
} catch(IO\NotFoundException $e) {
throw new Error("file_not_exists");
}
$this->response->setStatus(true);
return $this->response;
}
}
In the example above, the file's contents are obtained with the getFileContents method and passed to the View via the setData method.
Getting a File
The getFile method takes the file's path and name as a string, and its return value is an object of the File class.
The specified file does not need to exist.
Example:
<?php
namespace packages\packagename\controllers;
use themes\themename\views;
use packages\base\{Controller, Response, View, Http, Packages};
class Main extends Controller {
public function addDescription(): Response {
$view = View::byName(views\main\AddDescription::class);
$this->response->setView($view);
if (Http::is_post()) {
$input = $this->checkinputs([
'description' =>[
'type' => 'string'
]
]);
$file = Packages::package('packagename')->getFile("storage/public/description.txt");
$directory = $file->getDirectory();
if (!$directory->exists()) {
$directory->make(true);
}
$file->write($input['description']);
}
$this->response->setStatus(true);
return $this->response;
}
}
In the example above, the desired file is obtained by calling the getFile method, and then the existence of its parent directory is ensured (if the parent directory does not exist, it is created by calling the make method).
Next, the text received from the input is written to the file. If the file does not exist, it is created by calling the write method and the text is written into it. If the file already exists, the new text replaces the previous content.
Adding New Options
In addition to the routing, frontend, autoload, ... keys that are defined in the package structure file and must be set, the framework allows programmers to add their own options to the package structure file and use them during the program's execution.
For example, the programmer sets the storage path for uploaded files in this file, and in the program—instead of using a static path—calls the package's option.
The getOption method is defined for retrieving options. The method's input argument is the option's key.
In addition to declaring options in the structure file, you can set the desired option during the program's execution using the setOption method; however, note that this option must be set before it is retrieved and used.
With this approach, the option is not persisted and is only accessible until the end of that same request.
Sample configuration file:
{
"permissions": "*",
"routing": "routing.json",
"frontend": "frontend",
"autoload": {
"directories": ["controllers", "Models", "listeners", "events"]
},
"dependencies": ["userpanel"],
"languages":{
"fa_IR": "langs/fa_IR.json",
"en_US": "langs/en_US.json"
},
"events": [
{
"name": "packages/userpanel/events/usertype_permissions_list",
"listener": "listeners/settings/usertypes/Permissions@list"
}
],
"upload_path": "storage/public/upload/"
}
Example: How to use options
<?php
namespace packages\packagename\controllers;
use themes\themename\views;
use packages\packagename\User as Model;
use packages\base\{Controller, Response, View, Packages, NotFound};
class Users extends Controller {
public function updateAvatar($data): Response {
$user = Model::byId($data['id']);
if (!$user) {
throw new NotFound;
}
$view = view::byName(views\user\Info::class);
$this->response->setView($view);
$inputs = $this->checkinputs([
'img' =>[
'type' => 'image',
"max-size" => 2097152, // Byte
"obj" => true,
"extension" => array('jpeg', 'jpg'),
"resize" => [200, 200]
]
]);
$package = Packages::package('packagename');
$path = $package->getOption("upload_path") . $inputs["img"]->getFile()->md5() . "." . $inputs["img"]->getExtension();
$file = Packages::package("packagename")->getFile($path);
if (!$file->exists()) {
$directory = $file->getDirectory();
if (!$directory->exists()) {
$directory->make(true);
}
$image->saveToFile($file);
}
$user->avatar = $path;
$user->save();
$this->response->setData($package->url($path, true), "path");
$this->response->setStatus(true);
return $this->response;
}
}
The Bootstrap File
The framework defines a key named bootstrap. In this key, you specify the path to a PHP file, and after loading the package and before finding the routes and controllers, the framework calls and executes this file.
This file is used to perform operations—such as checking the user's IP—that must be done before the application runs.
The framework automatically handles registering and calling the bootstrap file using the setBootstrap and bootup methods.
Declaring the bootstrap file in the package.json file:
{
"permissions": "*",
"routing": "routing.json",
"frontend": "frontend",
"autoload": {
"directories": ["controllers", "Models", "listeners", "events", "bootstraps"]
},
"dependencies": ["userpanel"],
"languages":{
"fa_IR": "langs/fa_IR.json",
"en_US": "langs/en_US.json"
},
"events": [
{
"name": "packages/userpanel/events/usertype_permissions_list",
"listener": "listeners/settings/usertypes/Permissions@list"
}
],
"bootstrap": "bootstraps/checkAccess.php"
}
Sample bootstrap file:
<?php
namespace packages\packagename\bootstraps;
use packages\base\{Http, NotFound};
use packages\packagename\BannedIP as Model;
$userIP = Http::$client["ip"];
$model = new Model();
$model->where("ip", $userIP);
if ($model->has()) {
throw new NotFound();
}