Adjust image transformations

@param EventInterface $event
972699
public function adjustImageTransformations(EventInterface $event) {
        // If the image has not stepped through any input size transformations,
        // we don't set any ratio, and it should be safe to assume no transformations
        // parameters require any adjustment
        if (!$event->hasArgument('ratio')) {
            return;
        }

        $request = $event->getRequest();
        $transformations = $request->getTransformations();

        $ratio = $event->getArgument('ratio');
        $transformationIndex = $event->getArgument('transformationIndex');

        // Adjust coordinates according to the ratio between the original and the variation
        for ($i = 0; $i <= $transformationIndex; $i++) {
            $name = $transformations[$i]['name'];
            $params = $transformations[$i]['params'];
            $handler = $this->getTransformation($name);

            if ($handler instanceof InputSizeConstraint) {
                $params = $handler->adjustParameters($ratio, $params);

                $transformations[$i]['params'] = $params;
            }
        }

        $request->setTransformations($transformations);
    }
705395
public function convert(EventInterface $event)
    {
        $connection = $event->getConnection();

        $array = array(
            'message' => $event->getMessage(),
            'params' => $event->getParams(),
            'command' => $event->getCommand(),
            'connection' => array(
                'serverHostname' => $connection->getServerHostname(),
                'serverPort' => $connection->getServerPort(),
                'nickname' => $connection->getNickname(),
                'username' => $connection->getUsername(),
                'hostname' => $connection->getHostname(),
                'servername' => $connection->getServername(),
                'realname' => $connection->getRealname(),
            ),
        );

        if ($event instanceof UserEventInterface) {
            $array['user'] = array(
                'prefix' => $event->getPrefix(),
                'nick' => $event->getNick(),
                'username' => $event->getUsername(),
                'host' => $event->getHost(),
                'targets' => $event->getTargets(),
            );
        }

        if ($event instanceof CtcpEventInterface) {
            $array['ctcp'] = array(
                'command' => $event->getCtcpCommand(),
                'params' => $event->getCtcpParams(),
            );
        }

        return $array;
    }
747209
public function updateModel(EventInterface $event) {
        $image = $event->getArgument('image');

        if ($image->hasBeenTransformed()) {
            $image->setBlob($this->imagick->getImageBlob());
        }
    }
901792
public function dispatch(EventInterface $event)
    {
        if (array_key_exists($event->getName(), $this->listeners)) {
            foreach ($this->listeners[$event->getName()] as $listener) {
                $listener($event);
            }
        }

        return $event;
    }
1152172
public function setEvent(EventInterface $event)
    {
        $target = $this;

        if (!($event instanceof AuthenticationEvent)) {
            $eventParams = $event->getParams();
            $eventTarget = $event->getTarget();

            if ($eventTarget) {
                $target = $eventTarget;
            }

            $event = new AuthenticationEvent();

            $event->setParams($eventParams);
        }

        $event->setIdentity(null)->setTarget($target);

        $this->event = $event;

        return $this;
    }
375875
public function handle(EventInterface $event)
    {

        try {
            // load the application server instance
            /** @var \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface $applicationServer */
            $applicationServer = $this->getApplicationServer();

            // write a log message that the event has been invoked
            $applicationServer->getSystemLogger()->info($event->getName());

            // and initialize a console for each node found in the configuration
            /** @var \AppserverIo\Psr\Cli\Configuration\ConsoleConfigurationInterface $consoleNode */
            foreach ($applicationServer->getSystemConfiguration()->getConsoles() as $consoleNode) {
                /** @var \AppserverIo\Appserver\Core\Interfaces\ConsoleFactoryInterface $consoleFactory */
                $consoleFactory = $consoleNode->getFactory();

                // use the factory if available
                /** @var \AppserverIo\Appserver\Core\Interfaces\ConsoleInterface $console */
                $console = $consoleFactory::factory($applicationServer, $consoleNode);

                // register the console as service
                $applicationServer->bindService(ApplicationServerInterface::ADMINISTRATION, $console);
            }

        } catch (\Exception $e) {
            $applicationServer->getSystemLogger()->error($e->__toString());
        }
    }
574377
public function loadMetadata(EventInterface $event) {
        $request = $event->getRequest();
        $response = $event->getResponse();
        $user = $request->getUser();
        $imageIdentifier = $request->getImageIdentifier();
        $database = $event->getDatabase();

        $model = new Model\Metadata();
        $model->setData($database->getMetadata($user, $imageIdentifier));

        $response->setModel($model)
                 ->setLastModified($database->getLastModified([$user], $imageIdentifier));
    }
595605
public function getImage(EventInterface $event) {
        $request = $event->getRequest();
        $response = $event->getResponse();
        $eventManager = $event->getManager();

        $user = $request->getUser();
        $imageIdentifier = $request->getImageIdentifier();

        $image = new Model\Image();
        $image->setImageIdentifier($imageIdentifier)
              ->setUser($user);

        $response->setModel($image);

        // Load image details from database
        $eventManager->trigger('db.image.load');

        // Set a long max age as the image itself won't change
        $response->setMaxAge(31536000);

        // Custom Imbo headers, based on original
        $response->headers->add([
            'X-Imbo-OriginalMimeType' => $image->getMimeType(),
            'X-Imbo-OriginalWidth' => $image->getWidth(),
            'X-Imbo-OriginalHeight' => $image->getHeight(),
            'X-Imbo-OriginalFileSize' => $image->getFilesize(),
            'X-Imbo-OriginalExtension' => $image->getExtension(),
        ]);

        // Trigger loading of the image
        $eventManager->trigger('storage.image.load');

        // Trigger possible image transformations
        $eventManager->trigger('image.transform');
    }
983090
public function deleteImageShortUrls(EventInterface $event) {
        $request = $event->getRequest();
        $user = $request->getUser();
        $imageIdentifier = $request->getImageIdentifier();

        $event->getDatabase()->deleteShortUrls(
            $user,
            $imageIdentifier
        );

        if ($event->getName() === 'shorturls.delete') {
            // If the request is against the shorturls resource directly we need to supply a
            // response model. If this method is triggered because of an image has been deleted
            // the image resource will supply the response model
            $model = new ArrayModel();
            $model->setData([
                'imageIdentifier' => $imageIdentifier,
            ]);

            $event->getResponse()->setModel($model);
        }
    }
1263276
public function handle(EventInterface $event)
    {

        try {
            // load the application server and the naming directory instance
            /** @var \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface $applicationServer */
            $applicationServer = $this->getApplicationServer();
            /** @var \AppserverIo\Psr\Naming\NamingDirectoryInterface $namingDirectory */
            $namingDirectory = $applicationServer->getNamingDirectory();

            // initialize configuration and schema file name
            $configurationFileName = $applicationServer->getConfigurationFilename();

            // get an instance of our configuration tester
            $configurationService = new ConfigurationService(new InitialContext(new AppserverNode()));

            // load the parsed system configuration
            /** @var \DOMDocument $doc */
            $doc = $configurationService->loadConfigurationByFilename($configurationFileName);

            // validate the configuration file with the schema
            $configurationService->validateXml($doc, null, true);

            try {
                // query whether we're in configuration test mode or not
                if ($namingDirectory->search('php:env/args/t')) {
                    echo 'Syntax OK' . PHP_EOL;
                    exit(0);
                }

            } catch (NamingException $ne) {
                // do nothing, because we're NOT in configuration test mode
            }

            // initialize the SimpleXMLElement with the content XML configuration file
            $configuration = new Configuration();
            $configuration->initFromString($doc->saveXML());

            // initialize the configuration and the base directory
            $systemConfiguration = new AppserverNode();
            $systemConfiguration->initFromConfiguration($configuration);

            // re-initialize the container service with the real system configuration
            $configurationService->setSystemConfiguration($systemConfiguration);

            // then we can replace the system properties
            $properties = $configurationService->getSystemProperties();
            $systemConfiguration->replaceProperties($properties);

            // set the system configuration in the application server instance
            $applicationServer->setSystemConfiguration($systemConfiguration);

        } catch (\Exception $e) {
            // render the validation errors and exit immediately
            echo $e . PHP_EOL;
            exit(0);
        }
    }
1186954
public function generateVariations(EventInterface $event) {
        $eventManager = $event->getManager();
        $transformationManager = $event->getTransformationManager();

        $request = $event->getRequest();
        $user = $request->getUser();
        $originalImage = $request->getImage();
        $imageIdentifier = $originalImage->getImageIdentifier();
        $originalWidth = $originalImage->getWidth();

        // Fetch parameters specified in the Imbo configuration related to what sort of variations
        // should be generated
        $minWidth = $this->params['minWidth'];
        $maxWidth = $this->params['maxWidth'];
        $minDiff = $this->params['minDiff'];
        $scaleFactor = $this->params['scaleFactor'];

        // Remove widths which are larger than the original image
        $widths = array_filter($this->params['widths'], function($value) use ($originalWidth) {
            return $value < $originalWidth;
        });

        if ($this->params['autoScale'] === true) {
            // Have Imbo figure out the widths to generate in addition to the ones in the "width"
            // configuration parameter
            $variationWidth = $previousWidth = $originalWidth;

            while ($variationWidth > $minWidth) {
                $variationWidth = round($variationWidth * $scaleFactor);

                if ($variationWidth > $maxWidth) {
                    // Width too big, try again
                    continue;
                }

                if ((($previousWidth - $variationWidth) < $minDiff) || ($variationWidth < $minWidth)) {
                    // The diff is too small, or the variation is too small, stop generating more widths
                    break;
                }

                $previousWidth = $variationWidth;

                $widths[] = $variationWidth;
            }
        }

        foreach ($widths as $width) {
            // Clone the image so that the resize operation will happen on the original every time
            $image = clone $originalImage;

            try {
                // Trigger a loading of the image, using the clone of the original as an argument
                $eventManager->trigger('image.loaded', [
                    'image' => $image,

                    // Don't apply any sort of optimization to the image before saving, we want
                    // as high quality on the stored variation as possible
                    'skipOptimization' => true,
                ]);

                // If configured, use a lossless variation format
                if ($this->params['lossless'] === true) {
                    $transformationManager
                        ->getTransformation('convert')
                        ->setImage($image)
                        ->transform(['type' => 'png']);
                }

                // Trigger a resize of the image (the transformation handles aspect ratio)
                $transformationManager
                    ->getTransformation('resize')
                    ->setImage($image)
                    ->transform(['width' => $width]);

                // Trigger an update of the model
                $eventManager->trigger('image.transformed', [
                    'image' => $image,
                ]);

                // Store the image
                $this->storage->storeImageVariation($user, $imageIdentifier, $image->getBlob(), $width);

                // Store some data about the variation
                $this->database->storeImageVariationMetadata($user, $imageIdentifier, $image->getWidth(), $image->getHeight());
            } catch (TransformationException $e) {
                // Could not transform the image
                trigger_error(sprintf('Could not generate image variation for %s (%s), width: %d', $user, $imageIdentifier, $width), E_USER_WARNING);
            } catch (StorageException $e) {
                // Could not store the image
                trigger_error(sprintf('Could not store image variation for %s (%s), width: %d', $user, $imageIdentifier, $width), E_USER_WARNING);
            } catch (DatabaseException $e) {
                // Could not store metadata about the variation
                trigger_error(sprintf('Could not store image variation metadata for %s (%s), width: %d', $user, $imageIdentifier, $width), E_USER_WARNING);

                try {
                    $this->storage->deleteImageVariations($user, $imageIdentifier, $width);
                } catch (StorageException $e) {
                    trigger_error('Could not remove the stored variation', E_USER_WARNING);
                }
            }
        }
    }
787657
public function getImages(EventInterface $event) {
        $acl = $event->getAccessControl();

        $missingAccess = [];
        $users = $event->getRequest()->getUsers() ?: $event->getDatabase()->getAllUsers();

        foreach ($users as $user) {
            $hasAccess = $acl->hasAccess(
                $event->getRequest()->getPublicKey(),
                'images.get',
                $user
            );

            if (!$hasAccess) {
                $missingAccess[] = $user;
            }
        }

        if (!empty($missingAccess)) {
            throw new RuntimeException(
                'Public key does not have access to the users: [' .
                implode(', ', $missingAccess) .
                ']',
                400
            );
        }

        $event->getManager()->trigger('db.images.load', [
            'users' => $users
        ]);
    }
773812
public function loadFromCache(EventInterface $event) {
        $request = $event->getRequest();
        $response = $event->getResponse();

        // Generate the full file path to the response
        $path = $this->getCacheFilePath($request);

        if (is_file($path)) {
            $data = @unserialize(file_get_contents($path));

            // Make sure the data from the cache is valid
            if (
                is_array($data) &&
                isset($data['image']) &&
                isset($data['headers']) &&
                ($data['image'] instanceof Image) &&
                ($data['headers'] instanceof ResponseHeaderBag)
            ) {
                // Mark as cache hit
                $data['headers']->set('X-Imbo-TransformationCache', 'Hit');
                $data['image']->hasBeenTransformed(false);

                // Replace all headers and set the image model
                $response->headers = $data['headers'];
                $response->setModel($data['image']);

                // Stop other listeners on this event
                $event->stopPropagation();

                // Mark this as a cache hit to prevent us from re-writing the result
                $this->setCacheHit(true);

                return;
            } else {
                // Invalid data in the cache, delete the file
                unlink($path);
            }
        }

        // Mark as cache miss
        $response->headers->set('X-Imbo-TransformationCache', 'Miss');
    }
570296
public function handle(EventInterface $event)
    {

        try {
            // load the application server instance
            /** @var \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface $applicationServer */
            $applicationServer = $this->getApplicationServer();

            // unbind the loggers from the naming directory
            foreach (array_keys($applicationServer->getLoggers()) as $name) {
                $applicationServer->getNamingDirectory()->unbind(sprintf('php:global/log/%s', $name));
            }

            // set the initialized loggers finally
            $applicationServer->setLoggers(array());

        } catch (\Exception $e) {
            error_log($e->__toString());
        }
    }
651099
public function save(EventInterface $event) {
        $request = $event->getRequest();
        $database = $event->getDatabase();

        $user = $request->getUser();
        $imageIdentifier = $request->getImage()->getImageIdentifier();

        try {
            $database->updateMetadata(
                $user,
                $imageIdentifier,
                $this->properties
            );
        } catch (DatabaseException $e) {
            $database->deleteImage($user, $imageIdentifier);

            throw new RuntimeException('Could not store EXIF-metadata', 500);
        }
    }
249656
public function handle(EventInterface $event)
    {

        try {
            // load the application server, naming directory and system configuration instance
            /** @var \AppserverIo\Psr\ApplicationServer\ApplicationServerInterface $applicationServer */
            $applicationServer = $this->getApplicationServer();
            /** @var \AppserverIo\Psr\Naming\NamingDirectoryInterface $namingDirectory */
            $namingDirectory = $applicationServer->getNamingDirectory();
            /** @var \AppserverIo\Psr\ApplicationServer\Configuration\SystemConfigurationInterface $systemConfiguration */
            $systemConfiguration = $applicationServer->getSystemConfiguration();

            // initialize the loggers
            $loggers = array();
            foreach ($systemConfiguration->getLoggers() as $loggerNode) {
                $loggers[$loggerNode->getName()] = LoggerFactory::factory($loggerNode);
            }

            // register the logger callbacks in the naming directory
            foreach ($loggers as $name => $logger) {
                $namingDirectory->bind(sprintf('php:global/log/%s', $name), $logger);
            }

            // set the initialized loggers finally
            $applicationServer->setLoggers($loggers);

        } catch (\Exception $e) {
            $applicationServer->getSystemLogger()->error($e->__toString());
        }
    }
952273
public function subscribe(EventInterface $event) {
        $events = [];

        // Enable the event listener only for resources and methods specified
        foreach ($this->params['allowedMethods'] as $resource => $methods) {
            foreach ($methods as $method) {
                $eventName = $resource . '.' . strtolower($method);
                $events[$eventName] = ['invoke' => 1000];
            }

            // Always enable the listener for the OPTIONS method
            $eventName = $resource . '.options';
            $events[$eventName] = ['options' => 20];
        }

        $manager = $event->getManager();
        $manager->addCallbacks($event->getHandler(), $events);

        // Add OPTIONS to the Allow header
        $event->getResponse()->headers->set('Allow', 'OPTIONS', false);
    }