php – Joomla Migration – FastCGI Error Cannot declare class because the name is already in use

Today a perform a migration of a Joomla 3.8 site from a server to another. All works well except only one custom module. The module works correctly before the migration but after the migration the error received is this one:

2022/05/04 17:15:23 [error] 2572#0: *1 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Cannot declare class PdfToJpg, because the name is already in use in /www/wwwroot/readeat.it/Joomla/modules/mod_readeat_menu_upload/mod_readeat_menu_upload.php on line 7" while reading response header from upstream, client: 84.33.118.182, server: readeat.it, request: "POST /index.php/it/il-mio-locale/carica-menu HTTP/2.0", upstream: "fastcgi://unix:/tmp/php-cgi-74.sock:", host: "test.readeat.it", referrer: "https://test.readeat.it/index.php/it/il-mio-locale/carica-menu"

The old server was a built-in server with Plesk Obsidian and Apache server, now i migrate all to a NGinx based server. The version of PHP is 7.4 in both scenarios.

Here the Nginx configuration of the new server:

user  www www;
worker_processes auto;
error_log  /www/wwwlogs/nginx_error.log  crit;
pid        /www/server/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200;

stream {
    log_format tcp_format '$time_local|$remote_addr|$protocol|$status|$bytes_sent|$bytes_received|$session_time|$upstream_addr|$upstream_bytes_sent|$upstream_bytes_received|$upstream_connect_time';
  
    access_log /www/wwwlogs/tcp-access.log tcp_format;
    error_log /www/wwwlogs/tcp-error.log;
    include /www/server/panel/vhost/nginx/tcp/*.conf;
}

events
    {
        use epoll;
        worker_connections 51200;
        multi_accept on;
    }

http
    {
#AAPANEL_FASTCGI_CONF_BEGIN
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_path /dev/shm/nginx-cache/wp levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=1g;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
#AAPANEL_FASTCGI_CONF_END

        include       mime.types;
        #include luawaf.conf;

        include proxy.conf;

        default_type  application/octet-stream;

        server_names_hash_bucket_size 512;
        client_header_buffer_size 32k;
        large_client_header_buffers 4 32k;
        client_max_body_size 50m;

        sendfile   on;
        tcp_nopush on;

        keepalive_timeout 60;

        tcp_nodelay on;

        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 64k;
        fastcgi_buffers 4 64k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_intercept_errors on;

        gzip on;
        gzip_min_length  1k;
        gzip_buffers     4 16k;
        gzip_http_version 1.1;
        gzip_comp_level 2;
        gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
        gzip_vary on;
        gzip_proxied   expired no-cache no-store private auth;
        gzip_disable   "MSIE [1-6].";

        limit_conn_zone $binary_remote_addr zone=perip:10m;
        limit_conn_zone $server_name zone=perserver:10m;

        server_tokens off;
        access_log off;

server
    {
        listen 888;
        server_name phpmyadmin;
        index index.html index.htm index.php;
        root  /www/server/phpmyadmin;
            location ~ /tmp/ {
                return 403;
            }

        #error_page   404   /404.html;
        include enable-php.conf;

        location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }

        location ~ .*.(js|css)?$
        {
            expires      12h;
        }

        location ~ /.
        {
            deny all;
        }

        access_log  /www/wwwlogs/access.log;
    }
include /www/server/panel/vhost/nginx/*.conf;
}

And the code of the module:

<?php

/********************************************************************************************************************************************************* */
 
define("SKIP_API_CALL", "false");

class PdfToJpg {
    
    //Oggetto API
    private $ApiResource;

    private $numOfPages;
    private $saveFilePath;

    //Autenticazione
    private $projectPublic = "";
    private $projectSecret = "";
    private $baseFileName = "file_0";

    function __construct($projectPublic, $projectSecret) {
        
        $this->projectPublic = $projectPublic;
        $this->projectSecret = $projectSecret;

        //Recupero della libreria ILovePdf
        require_once(JPATH_LIBRARIES. '/ilovepdf/init.php');

        //Creazione dell'oggetto per interrogazione API
        $this->ApiResource = new IlovepdfIlovepdf($this->projectPublic, $this->projectSecret);
    }

    public function convertPdf($pdfFilePath, $pdfFileName) {

        if(SKIP_API_CALL != "true") {
            $restTask = $this->ApiResource->newTask('pdfjpg');
            $restTask->setOutputFilename($this->baseFileName);

            $restTask->addFile($pdfFilePath . $pdfFileName);

            $restTask->execute();
            $restTask->download($pdfFilePath);
        }
    }


    public function extractAndSave($filepath, $fileName, $newName = "menu") {

        //Elimino l'estensione del file
        $newName =  strstr($newName, '_', true);

        if (file_exists($filepath . $fileName)) {
           
            $zip = new ZipArchive();            
            $result = $zip->open($filepath . $fileName);
            
            if($result === true) {
    
                $this->numOfPages = $zip->numFiles;
                $result = $zip->extractTo($filepath);
                $zip->close();

                for($i=1; $i <= $this->numOfPages; $i++) {
                    $tmpOldName = $filepath . $this->baseFileName . "-" . str_pad($i, 4, '0', STR_PAD_LEFT) . ".jpg";
                    $tmpNewName = $filepath . $newName . "_" . $i . ".jpg";
                    rename($tmpOldName, $tmpNewName);
                }
                return true;
            } 
            else {  
                return false;
            }
        } 
        else {
           if(file_exists($filepath . $this->baseFileName . "-0001.jpg")) {
                $tmpOldName = $filepath . $this->baseFileName . "-0001.jpg";
                $tmpNewName = $filepath . $newName . "_1.jpg";
                rename($tmpOldName, $tmpNewName);
                return true;
            }
            else
                return false;
        }
    }

    public function getNumOfPages() {
        return $this->numOfPages;
    }
}

/********************************************************************************************************************************************************* */

class ReadEatPlaceProfile {

    private $placeIdOffset = 1000;

    public $name;
    public $timeWindow;
    public $id;
    public $ownerId;

    private $isNewUser = false;

    private static $joomlaDb;
    private static $isInitizlized = false;


    function __construct($userObj, $customFields, $joomlaDbObj) {   
        
        $this->setDBObject($joomlaDbObj);

        //Rimozione di tutti gli special Chars dalla stringa nome locale
        $this->name = preg_replace('/[^A-Za-z0-9-]/', '', $userObj->name);
        $this->timeWindow = $customFields[0]->value;
        $this->ownerId = $userObj->id;

        $tmpPlaceId = $this->getPlaceIdFromUserId();

        if($tmpPlaceId == NULL || !$tmpPlaceId) {
            $this->isNewUser = true;
            $this->id = $this->getNewPlaceId($userObj->id);
        }
        else {
            $this->id = $tmpPlaceId;
        } 
    }

    //Funzione epr l'inizializzazione degli oggetti contenenti le risorse Joomla
    public function initialize($joomlaDbObj) {
        if(!self::$isInitizlized) {
            setDBObject($joomlaDbObj);
        }    
    }

    //Query per il check della entry del locale all'interno delle tabelle readeat   
    public function getPlaceIdFromUserId() {

        $query = self::$joomlaDb->getQuery(true);

        $query->select('placeId')
                ->from(self::$joomlaDb->quoteName('rdet_locali'))
                ->where('userId = ' . $this->ownerId);
        
        self::$joomlaDb->setQuery($query); 
        $queryedPlaceId = self::$joomlaDb->loadResult();

        return $queryedPlaceId;
    }


    public function insertPlaceIdForUserid() {

        $query = self::$joomlaDb->getQuery(true);

        $query->insert(self::$joomlaDb->quoteName('rdet_locali'))
                ->columns(array('userId', 'placeId', 'placeName', 'timeWindow'))
                ->values("$this->ownerId, $this->id, '$this->name', '$this->timeWindow'");

        self::$joomlaDb->setQuery($query);
        self::$joomlaDb->execute();
    }


    public function insertNewMenuRecord($fileName, $fileType, $numOfPages, $data) {

        $name = preg_replace('/[/[^a-zA-Z0-9 ]/', '', $data['name']);
        $type = $data['type'];
        $lang = $data['lang'];
        $isPredefined = 0;
       
        if(!$this->menuExists($lang))
            $isPredefined = 1;

        self::$joomlaDb->transactionStart();

        $query = self::$joomlaDb->getQuery(true);
        $query->insert(self::$joomlaDb->quoteName('rdet_menu'))
                ->columns(array('placeId', 'isPredefined', 'language', 'type', 'name'))
                ->values("$this->id, $isPredefined, '$lang', '$type', '$name'");

        self::$joomlaDb->setQuery($query);
        self::$joomlaDb->execute();

        $query = self::$joomlaDb->getQuery(true);
        $query->insert(self::$joomlaDb->quoteName('rdet_files_menu'))
        ->columns(array('menuId', 'fileName', 'fileType', 'numberOfPages'))
        ->values("LAST_INSERT_ID(), '$fileName', '$fileType', '$numOfPages'");

        self::$joomlaDb->setQuery($query);
        self::$joomlaDb->execute();

        self::$joomlaDb->transactionCommit();
    }


    public function menuExists($language) {

        $query = self::$joomlaDb->getQuery(true);

        //Controllo che non sia giĆ  attivo un menu caricato
        $query->select(self::$joomlaDb->quoteName('menuId'))
                ->from(self::$joomlaDb->quoteName('rdet_menu'))
                ->where(self::$joomlaDb->quoteName('rdet_menu.placeId') . "=". self::$joomlaDb->quote($this->id) . " AND language = " . self::$joomlaDb->quote($language));
                self::$joomlaDb->setQuery($query); 
        $menuIdExsists = self::$joomlaDb->loadResult();

        if($menuIdExsists == NULL || !$menuIdExsists)
            return false;
        return true;
    }

    public function isNewUser() {  
        return $this->isNewUser;
    }


    private function setDBObject($joomlaDbObj) {
        self::$joomlaDb = $joomlaDbObj;
    }
    

    private function getNewPlaceId($currentUserid) {
        return (int)$currentUserid + $this->placeIdOffset;
    }


    public function getPlaceId() {
        return $this->id;
    }
}

/********************************************************************************************************************************************************* */

class ReadEatMenuUpload {

    //Oggetto Locale
    public $ReadEatPlaceProfile;

    private $menuFilePath;
    private $filesExtension;
    private $filesNumber;
    private $tmpFiles;
    private $pdfConverter;
    private $fileName;

    //Impostazioni
    private $MODULE_PARAM = array();


function __construct($MODULE_PARAM) { 
    
    $this->fileName = "";
    $this->MODULE_PARAM = $MODULE_PARAM;

    //Oggetto PDF Converter
    $this->pdfConverter = new PdfToJpg($MODULE_PARAM['API_PUBLIC'], $MODULE_PARAM['API_SECRET']);

    $currentUserId = JFactory::getUser()->id;

    $this->ReadEatPlaceProfile = new ReadEatPlaceProfile(JFactory::getUser(), FieldsHelper::getFields('com_users.user', ['id'=> $currentUserId]), JFactory::getDBO());
}

public function checkAuthorization($currentUserGroups) {

    foreach($this->MODULE_PARAM['ALLOWED_GROUPS'] as $allowedGroups) 
        foreach($currentUserGroups as $userGroup) 
            if($userGroup == $allowedGroups)
                return true;

    return false;
}

public function handlefiles($filesArray, $data) {
        
    $this->tmpFiles = $filesArray;
    $this->filesNumber = count($this->tmpFiles["name"]);
    
    if($this->filesNumber > $this->MODULE_PARAM['MAX_FILE_TO_UPLOAD']) {
        if($DEBUG_MODE == 1) {
            $page .= "<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_MAX_FILE_ERR' ) . "</p>";
        }       
    }

    //Preparo nomi e percorso di salvataggio
    $this->menuFilePath = $this->MODULE_PARAM['FILE_SAVE_PATH'] . strval($this->ReadEatPlaceProfile->getPlaceId()) . "/";

    if($this->checkfileType()) {
        if($this->saveFiles()) {

            if($this->filesExtension == "pdf") {
                $this->ReadEatPlaceProfile->insertNewMenuRecord($this->fileName, ".jpg", $this->pdfConverter->getNumOfPages(), $data);
            }
            else {
                $this->ReadEatPlaceProfile->insertNewMenuRecord($this->fileName, "." . $this->filesExtension, $this->filesNumber, $data);
            }
            header("location: " . JUri::base() . "index.php" . "/" . $this->MODULE_PARAM['ON_SUCCESS_UPLOAD_ALIAS']);
        }
    }
    else {
        $message = "<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_UPLOAD_ERR' ) . "</p>";
        JFactory::getApplication()->enqueueMessage($message, "error");      
    }
}


public function saveFiles() {
    
    if($this->MODULE_PARAM['TIMESTAMP_FILE_NAME'] == 1) {
        $date = new DateTime();
        $this->fileName = $date->getTimestamp();
    }
    else {
        $this->fileName = $this->MODULE_PARAM['BASE_FILE_NAME'];
    }

    for($i=0; $i < $this->filesNumber; $i++) { 

        //Aggiungo al nome del file l'indice specifico e l'estensione
        $localFileName = $this->fileName . "_" . strval($i+1) . "." . $this->filesExtension;    
        
        if(!JFile::upload($this->tmpFiles['tmp_name'][$i], $this->menuFilePath . $localFileName)) {
            //Qui fallisce la chiamata joomla all'upload                        
            JFactory::getApplication()->enqueueMessage("<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_FILE_ERR' ) . "</p>", "error");

            return false;
        }
        else {

            if($this->filesExtension == "pdf") {

                $this->pdfConverter->convertPdf($this->menuFilePath, $localFileName);                
                $result = $this->pdfConverter->extractAndSave($this->menuFilePath, "output.zip", $localFileName);   

                if($result) {
                    JFactory::getApplication()->enqueueMessage("<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_UPLOAD_OK' ) . "</p>");
                    return true;
                }
                else {
                    JFactory::getApplication()->enqueueMessage("<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_CONV_ERR' ) . "</p>");
                    return false;  
                }
            }
        }
    }
    JFactory::getApplication()->enqueueMessage("<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_UPLOAD_OK' ) . "</p>");
    return true;
}


public function checkfileType() {

    for($i = 0; $i < $this->filesNumber; $i++) {            

        //Variabili di stato per il controllo degli errori e gli step
        $typeError = true;
        $mimeTypeError = true;

        //Controllo dell'estensione
        $uploadedFileNameParts = explode('.', $this->tmpFiles['name'][$i]);
        $uploadedFileExtension = strtolower(array_pop($uploadedFileNameParts));

        //Controllo singolo file in caso di pdf
        if($uploadedFileExtension == "pdf" && $this->filesNumber > 1) {
            $message = "<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_MORE_PDF_ERR' ) . "</p>";
            JFactory::getApplication()->enqueueMessage($message, "error");
            return false;
        }

        //Controllo che le estensioni siano tutte uguali
        if(!empty($filesExtension)) {
            if($this->filesExtension != $uploadedFileExtension) {
                //Basta una sola estensione diversa per far fallire l'upload
                return false;
            }
        }

        //Controllo che l'estensione corrisponda a quelle consentite
        foreach($this->MODULE_PARAM['ALLOWED_EXTENSIONS'] as $key => $value) {
            if($value == $uploadedFileExtension) {

                //trovo una corrispondenza quindi esco
                if(empty($filesExtension))
                    $this->filesExtension = $uploadedFileExtension;

                $typeError = false;
                break;
            }
            else {
                $typeError = true;
            }
        }
                    
        //Controllo che i files siano effettivamente una immagine o un pdf per questioni di security
        //Il meccanismo sfrutta i MIME Types
        $fileInfo = mime_content_type($this->tmpFiles['tmp_name'][$i]); 

        foreach($this->MODULE_PARAM['ALLOWED_MIME_TYPES'] as $key => $value) {

            if($value == $fileInfo) {
                //Trovo una corrispondenza quindi esco
                $mimeTypeError = false;
                break;
            }
            else {
                $mimeTypeError = true;
            }
        }
    }
    return !($mimeTypeError || $typeError);
} 

public function isNewUser() {
    return $this->ReadEatPlaceProfile->isNewUser();
}

public function insertPlaceIdForUserid() {
    $this->ReadEatPlaceProfile->insertPlaceIdForUserid();
}

public function menuExists() {
    return $this->ReadEatPlaceProfile->menuExists();
}

public function getUploadedPlaceId() {
    return $this->ReadEatPlaceProfile->getPlaceId();
}
}


/********************************************************************************************************************************************************* */


use JoomlaCMSFactory;

$MODULE_PARAM = array();

//Parametri per gruppi consentiti
$MODULE_PARAM['ALLOWED_GROUPS'] = explode(",", $params->get('allowed_groups', "locali"));

//Parametri per redirect
$MODULE_PARAM['AUTH_ERROR_ALIAS'] = $params->get('auth_error_alias', "locali");
$MODULE_PARAM['ON_SUCCESS_UPLOAD_ALIAS'] = $params->get('success_upload_alias', "rdetqrviewer");
$MODULE_PARAM['EDIT_PROFILE_ALIAS'] = JUri::base() . "index.php" . "/" . $params->get('edit_profile_alias', "il-mio-profilo");

//Parametri per l'upload
$MODULE_PARAM['BASE_FILE_NAME'] = $params->get('base_file_name', "menu");
$MODULE_PARAM['TIMESTAMP_FILE_NAME'] = (int)$params->get('ts_file_name', 0);
$MODULE_PARAM['MAX_FILE_TO_UPLOAD'] = (int)$params->get('max_file_upload', 40);
$MODULE_PARAM['ALLOWED_EXTENSIONS'] = explode(',', $params->get('allowed_extensions', "jpeg,jpg,png,pdf"));
$MODULE_PARAM['ALLOWED_MIME_TYPES'] = explode(',', $params->get('allowed_mime_types', 'image/jpeg,image/pjpeg,image/png,image/x-png,application/pdf'));
$MODULE_PARAM['FILE_SAVE_PATH'] = JPATH_ROOT . "/" . $params->get('file_save_path', "readeat/menus/");

//Debug variables
$MODULE_PARAM['API_PUBLIC'] = $params->get('ilovepdf_api_public', "project_public_a5113e260b65faf6a453c6a976ba303d_T1Oon5dc7b86cd720576593cf39c8bd561f8e");
$MODULE_PARAM['API_SECRET'] =$params->get('ilovepdf_api_secret', "secret_key_cf0c0bc1a7699937817ccc19319c43cc_o-3zIb2e8cd02e98f4e673a8c9bec9ae153e0");
$MODULE_PARAM['DEBUG_MODE'] = (int)$params->get('debug_mode', 0);


$page = "";

$readEatMenuUpload = new ReadEatMenuUpload($MODULE_PARAM);

$currentUserGroups = JFactory::getUser()->groups;

if(!$readEatMenuUpload->checkAuthorization($currentUserGroups)) {
    //L'utente non fa parte del gruppo autorizzati
    header("location: " . JUri::base() . "index.php" . "/" . $AUTH_ERROR_ALIAS);
}


//Oggetti Joomla
$doc = JFactory::getDocument();

if($readEatMenuUpload->isNewUser())
$readEatMenuUpload->insertPlaceIdForUserid();   

//Gestione dei file caricati
if(isset($_FILES['menuFile'])) {
    
    if(empty($_POST['menuName'])) {
        $message = "<p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_NONAME_ERROR' ) . "</p>";
        JFactory::getApplication()->enqueueMessage($message, "error");
    }
    else {
        $data = array();
        $data['name'] = $_POST['menuName'];
        $data['type'] = $_POST['menuType'];
        $data['lang'] = $_POST['menuLang'];    

        $readEatMenuUpload->handlefiles($_FILES['menuFile'], $data);
    }
}

$message = "
    <p class="rdetInfoMessage">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_MSG_HOWTO' ) . "</p>
";

$page .= "

    <button onclick='showHelp()' class="helpButton">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_BUTTON' ) . "</button>

    <div id='rdetUploadDiv'>
        <form data-intro='" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_INTRO' ) . "' id='rdetUploadForm' method='POST' enctype="multipart/form-data"'>
            <div data-intro='" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_NAME' ) . "' class="rdetFieldContainer">
                <label class="rdetFormLabel" for="rdetMenuName">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_MENU_NAME' ) . "</label>
                <input type="text" id='rdetMenuName' name="menuName">
            </div>

            <div data-intro='" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_TYPE' ) . "' class="rdetFieldContainer">
                <label class="rdetFormLabel" for="rdetMenuType">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_MENU_TYPE' ) . "</label>
                <select id='rdetMenuType' name="menuType">
                    <option value="cucina">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_COOK' ) . "</option>
                    <option value="vini">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_WINE' ) . "</option>
                    <option value="cocktail">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_COCKTAIL' ) . "</option>
                    <option value="dolci">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_DESSERT' ) . "</option>
                    <option value="allergeni">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_ALLERGENS' ) . "</option>
                    <option value="altro">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_TYPE_OTHER' ) . "</option>
                </select>
            </div>

            <div data-intro='" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_LANG' ) . "' class="rdetFieldContainer">
                <label class="rdetFormLabel" for="rdetMenuLang">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_LANG' ) . "</label>
                <select id='rdetMenuLang' name="menuLang">
                    <option value="it-IT">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_IT' ) . "</option>
                    <option value="en-GB">" . JText::_( 'MOD_READEAT_MENU_UPLOAD_LBL_EN' ) . "</option>
                </select>
            </div>

            <div class="rdetFieldContainer">
                <input data-intro='" . JText::_( 'MOD_READEAT_MENU_UPLOAD_HELP_FILE' ) . "' class="btn rdetUploadInput" type="file" name="menuFile[]" multiple>
                <input class="button rdetUploadInput" type="submit" value="" . JText::_( "MOD_READEAT_MENU_UPLOAD_LBL_UPLOAD' ) . "'>
            </div>
        </form>
    </div>
";

JFactory::getApplication()->enqueueMessage($message);


$doc->addStyleSheet(JURI::root(true) . "/modules/mod_readeat_menu_upload/libs/introjs/introjs.min.css");
$doc->addScript(JURI::root(true) . '/modules/mod_readeat_menu_upload/libs/introjs/intro.min.js');
$doc->addStyleSheet(JURI::root(true) . "/modules/mod_readeat_menu_upload/css/default.css");
$doc->addScript(JURI::root(true) . '/modules/mod_readeat_menu_upload/js/script.js');

require JModuleHelper::getLayoutPath('mod_readeat_menu_upload', $params->get('layout', 'default'));

?>

Do someone see this before?

thanks

Leave a Comment