Dynamic filter with liipImagineBundle - image

I'm using liipImagineBundle and am trying to apply a filter directly into a controller.
In the doc I found two sections in which explains how to use liipImagineBundle from the controller. This one https://github.com/liip/LiipImagineBundle#using-the-controller-as-a-service
public function indexAction()
{
// RedirectResponse object
$imagemanagerResponse = $this->container
->get('liip_imagine.controller')
->filterAction(
$this->getRequest(),
'uploads/foo.jpg', // original image you want to apply a filter to
'my_thumb' // filter defined in config.yml
);
// string to put directly in the "src" of the tag <img>
$srcPath = $imagemanagerResponse->headers->get('location');
// ..
}
And https://github.com/liip/LiipImagineBundle/blob/master/Resources/doc/filters.md#dynamic-filters
public function filterAction(Request $request, $path, $filter)
{
$targetPath = $this->cacheManager->resolve($request, $path, $filter);
if ($targetPath instanceof Response) {
return $targetPath;
}
$image = $this->dataManager->find($filter, $path);
$filterConfig = $this->filterManager->getFilterConfiguration();
$config = $filterConfig->get($filter);
$config['filters']['thumbnail']['size'] = array(300, 100);
$filterConfig->set($filter, $config);
$response = $this->filterManager->get($request, $filter, $image, $path);
if ($targetPath) {
$response = $this->cacheManager->store($response, $targetPath, $filter);
}
return $response;
}
I tested as indicated in "Using the controller as a service" and it works, the problem I have is that I don't know how to access the filter settings to modify it.
liip_imagine:
driver: gd
web_root: %kernel.root_dir%/../web
data_root: %kernel.root_dir%/../web
cache_mkdir_mode: 0777
cache_prefix: /media/cache
cache: web_path
cache_clearer: true
data_loader: filesystem
controller_action: liip_imagine.controller:filterAction
formats: []
filter_sets:
my_thumb:
filters:
crop: { start: [0, 0], size: [200, 150] }
my_paste:
quality: 90
filters:
paste: { start: [30, 60], image: ../web/uploads/images/firma.jpg }
The second, really, I don't understand when he says "With a custom data loader...".
In the example he is only modifying the method filteraction() from the ImagineController class (Liip\ImagineBundle\Controller). I wonder how I can modify that method dynamically? For example from my controller indexAction().
Also i have read this post https://stackoverflow.com/questions/16166719/loading-your-custom-filters-with-liipimaginebundle where #NSCoder says that "You can use the built in filter and modify their configuration." but i don't understand it.
I've been looking for several days but I haven't found an example from which to start.

Looking for some more I found another LiipImagineBundle topic (Use LiipImagineBundle to Resize Image after Upload?) that has helped me to do what I wanted..
here I leave the code I use to dynamically apply a filter
public function indexAction()
{
$container = $this->container;
# The controller service
$imagemanagerResponse = $container->get('liip_imagine.controller');
# The filter configuration service
$filterConfiguration = $container->get('liip_imagine.filter.configuration');
# Get the filter settings
$configuracion = $filterConfiguration->get('my_thumb');
# Update filter settings
$configuracion['filters']['crop']['size'] = array(50, 150);
$configuracion['filters']['crop']['start'] = array(10, 10);
$filterConfiguration->set('my_thumb', $configuracion);
# Apply the filter
$imagemanagerResponse->filterAction($this->getRequest(),'uploads/images/logo.jpg','my_thumb');
# Move the img from temp
$fileTemporal = new File('media/cache/my_thumb/uploads/images/logo.jpg');
$fileTemporal->move('uploads/images/', 'mini-logo.jpg');
####################################
}

Related

How to implement required File upload attribute, on Update action, in Yii 2?

I need file upload field to be required for both Create and Update actions, and the required validation and validation of types to be performed in both cases.
This is how my form looks like (Note: It's a form, not an Active Record model):
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\base\Object;
use yii\helpers\FileHelper;
class MyCustomForm extends Model
{
public $file_image;
public function rules()
{
return [
[
[['file_image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'jpg, jpeg, png, bmp, jpe']
]
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
//Scenarios Attributes that will be validated
$scenarios['action_add'] = ['file_image'];
$scenarios['action_edit'] = ['file_image'];
return $scenarios;
}
}
And this is how my controller actions looks like.
The Create action works as expected (on POST request I'm taking the Uploaded File with UploadedFile::getInstance command)
public function actionCreate()
{
$model_form = new MyCustomForm(['scenario' => 'action_add']);
if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
$model_form->file_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");
if($model_form->validate()) {
if(isset($model_form->file_image)){
//I'm uploading my image to some cloud server here
//creating corresponding $model_entity for database, fill with the data from the form and save it
$model_entity->save();
}
}
}
}
But I'm facing with an issue when doing the same on Update action. In database I have the URL of image that is on third party cloud server and I can access it and display the image in my form (so GET request on Update works, I'm getting the corresponding entity from database and fill the form with data). But for POST, file validation is failing, if I don't have file assigned in the model and the POST request for Update is not working.
public function actionUpdate($id)
{
$model_entity = $this->findModel($id);
$image_URL = //I'm having URL to corresponding image here;
$model_form = new MyCustomForm(['scenario' => 'action_edit']);
$model_form_data = [$model_form->formName() => $model_entity->attributes];
$model_form->load($model_form_data);
if (Yii::$app->request->isPost && $model_form->load(Yii::$app->request->post())) {
//if we upload image again this will work
//NOTE: I have another text fields in the form and If I only change them
//and if I don't change the file image, the following result will return NULL and validation will fail
$file_uploaded_image = \yii\web\UploadedFile::getInstance($model_form, "file_image");
if(isset($file_uploaded_image)){
//new image is uploaded on update, this scenario will be OK
} else {
//no image is uploaded on update, this scenario will fail
}
if($model_form->validate()) {
//this will fail if I don't upload image on Update
}
}
}
I have tried many things in Update action, before validation, in order to find a workaround to get the image and validation to not fail. For example:
$dataImg = file_get_contents($image_URL);
$model_form->file_image = $dataImg;
or trying to do get with temporary file:
$dataImg = file_get_contents($dataImg);
$filePath = \yii\helpers\FileHelper::createDirectory("/images/tmp/test.png", 777);
file_put_contents($filePath, $dataImg);
$model_form->file_image = $filePath;
But none of them is working. Is there any solution to this scenario?
Note that I will have to use a Froms (as above) and not the ActiveRecord, since my real project is more complex that example listed.
Write this code in your Model(MyCustomForm) :
class MyCustomForm extends Model
{
public $file_image;
public function rules()
{
return [
[['file_image',],'required','on'=>['create','update']],
[['file_image'], 'file','extensions' => 'jpg, jpeg, png, bmp, jpe'],
];
}
}
Write this code in your actionCreate() :
$model_form = new MyCustomForm();
$model_form->scenario = "create";
Write this code in your actionUpdate() :
$model_form = new MyCustomForm();
$model_form->scenario = "update";
Or you can add scenario by this :
$model_form = new MyCustomForm(['scenario' => 'create']);
I have tried this and it is working.

Having problems with creating image cache with Intervention \ Image

So heres my code
public static function getImageThumb($link) {
$domain = substr(Request::root(), 7);
if(starts_with(Request::root(), 'http://')) {
$domain = substr(Request::root(), 7);
}
$link = $domain.$link; // This is prety much something like this domain.name/uploads/image/13_0.jpeg
$img = Image::cache(function ($image) use ($link) {
return $image->make($link)->resize(230, 140);
}, 5, true);
return $img;
}
And it gives me this:
Intervention \ Image \ Exception \ NotReadableException
Image source not readable
I dont really know whats wrong here..
Thanks for help!
EDIT-------------------------
I fixed it like this:
public static function getImageThumb($link) {
$link = trim($link, '/');
$img = Image::cache(function ($image) use ($link) {
return $image->make($link)->resize(230, 140);
}, 5, true);
return $img;
}
But how do i get the link to img now? So i can place it in src for img tag.
If you're going to use a URL as the source parameter for the make method, make sure it includes the scheme as well, or it will consider it to be a local file path. So get rid of the part where you strip the http:// from the URL, just use:
public static function getImageThumb($link)
{
$link = Request::root() . $link;
$img = Image::cache(function ($image) use ($link) {
return $image->make($link)->resize(230, 140);
}, 5, true);
return $img;
}
Also, since the image not from a remote domain, it makes more sense to just read it from the filesystem, instead of making a HTTP request for it:
public static function getImageThumb($link)
{
$path = public_path() . $link;
$img = Image::cache(function ($image) use ($path) {
return $image->make($path)->resize(230, 140);
}, 5, true);
return $img;
}
To return the cached version of a image, you have to have a dedicated route that retrieves the resized image. Something like this should do:
Route::get('/images/{link}', function ($link)
{
// Repo will be the class implementing your getImageThumb method
$img = Repo::getImageThumb($link);
// This makes sure the HTTP response contains the necessary image headers
return $img->response();
});
Now in your blade Blade template file you generate the URL like so:
<img src="{{ asset('/images/' . $link) }}">
By prepending /images to the actual link path you're hitting the route that is going to use the image cache if it is available. So your links would now look like this:
http://domain.name/images/uploads/image/13_0.jpeg
instead of
http://domain.name/uploads/image/13_0.jpeg
Of course you can use anything you like as the path prefix, not necessarily /images.

How to get Response of REST API in JSON format by Default in Magento

In magento as we use the REST url to access the data,as http://localhost/magemto/api/rest/products it returns in XML format.
But as my team requirement, I should send the data in JSON format to access AJAX calls easily.. I have used REST client to include a header as 'Content-Type:appilcation/json'.. Then it returns in JSON format.. But I want it as defaultly by the magento API..
Hey, I do have a solution for this, I would like to share with you.
First go to your magento root folder then go to following path
\app\code\core\Mage\Api2\Model\Request.php
Go to the method getAccepTypes() and change with this code below it will fulfill your requirement.
public function getAcceptTypes()
{
$qualityToTypes = array();
$orderedTypes = array();
foreach (preg_split('/,\s*/', $this->getHeader('Accept')) as $definition) {
$typeWithQ = explode(';', $definition);
$mimeType = trim(array_shift($typeWithQ));
// check MIME type validity
if (!preg_match('~^([0-9a-z*+\-]+)(?:/([0-9a-z*+\-\.]+))?$~i', $mimeType)) {
continue;
}
$quality = '1.0'; // default value for quality
if ($typeWithQ) {
$qAndValue = explode('=', $typeWithQ[0]);
if (2 == count($qAndValue)) {
$quality = $qAndValue[1];
}
}
$qualityToTypes[$quality][$mimeType] = true;
}
krsort($qualityToTypes);
foreach ($qualityToTypes as $typeList) {
$orderedTypes += $typeList;
}
unset($orderedTypes);
$orderedTypes=Array
("application/json" => 1);
return array_keys($orderedTypes);
}
Hope this help you.

TYPO3 Extbase: How to render the pagetree from my model?

I want to create some kind of sitemap in extbase/fluid (based on the pagetree). I have loaded the pages table into a model:
config.tx_extbase.persistence.classes.Tx_MyExt_Domain_Model_Page.mapping.tableName = pages
I have created a controller and repository, but get stuck on the part wich can load the subpages as relation into my model.
For example:
$page = $this->pageRepository->findByPid($rootPid);
Returns my rootpage. But how can I extend my model that I can use $page->getSubpages() or $page->getNestedPages()?
Do I have to create some kind of query inside my model? Or do I have to resolve this with existing functions (like the object storage) and how?
I tried a lot of things but can simply figure out how this should work.
you have to overwrite your findByPid repository-method and add
public function findByPid($pid) {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
$query = $this->createQuery();
$query->matching($query->equals('pid', $pid));
$pages = $query->execute();
return $pages;
}
to get all pages. Than you can write your own getSubpages-method like
function getSubpages($currentPid) {
$subpages = $this->pagesRepository->findByPid($currentPid);
if (count($subpages) > 0) {
$i = 0;
foreach($subpages as $subpage) {
$subpageUid = $subpage->getUid();
$subpageArray[$i]['page'] = $subpage;
$subpageArray[$i]['subpages'] = $this->getSubpages($subpageUid);
$i++;
}
} else {
$subpageArray = Array();
}
return $subpageArray;
}
i didn't test this method, but it looks like this to get alle subpages.
i wonder that i couldĀ“t find a typo3 method that return the complete Page-Tree :( So i write a little function (you can use in an extbase extension), for sure not the best or fastes way, but easy to extend or customize ;)
first you need an instance of the PageRepository
$this->t3pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
this->t3pageRepository->init();
make the init, to set some basic confs, like "WHERE deletet = 0 AND hidden = 0..."
then with this function you get an array with the page data and subpages in. I implement yust up to three levels:
function getPageTree($pid,$deep=2){
$fields = '*';
$sortField = 'sorting';
$pages = $this->t3pageRepository->getMenu($pid,$fields,$sortField);
if($deep>=1){
foreach($pages as &$page) {
$subPages1 = $this->t3pageRepository->getMenu($page['uid'],$fields,$sortField);
if(count($subPages1)>0){
if($deep>=2){
foreach($subPages1 as &$subPage1){
$subPages2 = $this->t3pageRepository->getMenu($subPage1['uid'],$fields,$sortField);
if(count($subPages2>0)){
$subPage1['subpages'] = $subPages2;
}
}
}
$page['subpages'] = $subPages1;
}
}
}
return $pages;
}

Image Sitemap with Zend_Navigation

I generate a Sitemap using Zend_Navigation and i wanted to add images to this sitemap, now i got no Idea how to get this done, i use following (working) code to generate the sitemap
foreach($sitemapItems as $item)
{
$newSite = new Zend_Navigation_Page_Uri();
$newSite->uri = 'http://' . $_SERVER['HTTP_HOST'] . $item->getSpeakingUrl();
$newSite->lastmod = $item->getUpdatedAt();
$newSite->changefreq = 'weekly';
$this->_navigation->addPage($newSite);
}
$this->view->navigation($this->_navigation);
$this->view->navigation()->sitemap()->setFormatOutput(true);
The Output is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://test.dev/pictures/site-28.html</loc>
<lastmod>2010-03-11T17:47:30+01:00</lastmod>
<changefreq>weekly</changefreq>
</url>
....
I need the following Output inside the Url part
<image:image>
<image:loc>http://example.com/image.jpg</image:loc>
</image:image>
i tried to just set
$newSite->image = URI
but it didnt work also i tried to add custom attribute via
$newSite->__set('image', array('loc' => URI));
Does anyone know if what i want is even possible ? i cant find anything in the docs or web...
Thanks for your time,
Dominik
Oki so first what you need to do is extend Zend_Navigation_Page_Uri and add you're image var to it smth like below :
class Mylib_NavPageUriImage extends Zend_Navigation_Page_Uri
{
protected $_image = null;
public function setImage($image)
{
if (null !== $image && !is_string($image)) {
require_once 'Zend/Navigation/Exception.php';
throw new Zend_Navigation_Exception(
'Invalid argument: $image must be a string or null');
}
$this->_image = $image;
return $this;
}
public function getImage()
{
return $this->_image;
}
public function toArray()
{
return array_merge(
parent::toArray(),
array(
'image' => $this->getImage()
));
}
}
Add this class to library/Mylib/NavPageUriImage.php.
To make it usable you need to register the namespace ( i like to register my namespaces at bootstrap but it can be done from app.ini too ) so in you're bootstrap class add the following :
function _initNamespace()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Mylib_');
}
Then in you're controller you can now use :
$newSite = new Mylib_NavPageUriImage();
$newSite->uri = 'http://' . $_SERVER['HTTP_HOST'] . $item->getSpeakingUrl();
$newSite->lastmod = $item->getUpdatedAt();
$newSite->changefreq = 'weekly';
$newSite->image = 'some image';
THE FOLLOWING IS NOT RECOMENDED , YOU NEED TO EXTEND YOU'RE OWN NAVIGATION HELPER AND USE THAT ( i just don't have the time to play with it now ) ALLSO ADD YOU'RE OWN imageValidator
And then in library/zend/view/helper/navigation/sitemap.php add the following lines ( under the add priority element if statement , mine ends at 443 so i added this at 444 ) :
// add 'image' element if a valid image is set in page
if (isset($page->image)) {
$image = $page->image;
$imgDom = $dom->createElementNS(self::SITEMAP_NS, 'image:image');
$imgDom->appendChild($dom->createElementNS(self::SITEMAP_NS, 'image:loc', $image));
$urlNode->appendChild($imgDom);
}

Resources