The controller must return a response (Object(AppBundle\\Entity\\User) given) - rest

I got this message "The controller must return a response (Object(App Bundle\Entity\User) given)." when i try to PATCH with postman a user password or username ... please help
BUT the username or password change ... ! i don't know why but that's working just the message is not good ...
My Userscontroller :
use AppBundle\Entity\EntityMerger;
use AppBundle\Entity\User;
use AppBundle\Exception\ResourceValidationException;
use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use FOS\RestBundle\Controller\Annotations as Rest;
/**
* #Security("is_anonymous() or is_authenticated()")
*/
class UsersController extends AbstractController
{
/**
* #var UserPasswordEncoderInterface
*/
private $passwordEncoder;
/**
* #var JWTEncoderInterface
*/
private $jwtEncoder;
/**
* #var EntityMerger
*/
private $entityMerger;
/**
* UsersController constructor.
* #param UserPasswordEncoderInterface $passwordEncoder
* #param JWTEncoderInterface $jwtEncoder
* #param EntityMerger $entityMerger
*/
public function __construct(UserPasswordEncoderInterface $passwordEncoder, JWTEncoderInterface $jwtEncoder, EntityMerger $entityMerger)
{
$this->passwordEncoder = $passwordEncoder;
$this->jwtEncoder = $jwtEncoder;
$this->entityMerger = $entityMerger;
}
/**
* #Rest\View()
* #Security("is_granted('show', theUser)", message="Access denied")
*/
public function getUserAction(?User $theUser)
{
if (null === $theUser) {
throw new NotFoundHttpException();
}
return $theUser;
}
/**
*
* #Rest\Post(
* path = "/users",
* name = "users_add"
* )
* #Rest\View(StatusCode=201)
* #ParamConverter(
* "user",
* converter="fos_rest.request_body",
* options={"deserializationContent"={"groups"={"Deserialize"}}}
* )
*/
public function postUserAction(User $user,
ConstraintViolationListInterface $violations)
{
if (count($violations) > 0) {
$message = 'The user is not valid: ';
foreach ($violations as $violation) {
$message .= sprintf(
"Field %s: %s ",
$violation->getPropertyPath(),
$violation->getMessage()
);
}
throw new ResourceValidationException($message);
}
$this->encodePassword($user);
$user->setRoles([User::ROLE_USER]);
$this->persistUser($user);
return $user;
}
/**
* #Rest\Patch(
* path = "/users/{theUser}",
* name= "patch_user"
* )
* #ParamConverter(
* "modifiedUser",
* converter="fos_rest.request_body",
* options={
* "validator"={"groups"={"Patch"}},
* "deserializationContext"={"groups"={"Deserialize"}}
* }
* )
* #Security("is_granted('edit', theUser)", message="Access Denied")
*/
public function patchUserAction(?User $theUser, User $modifiedUser,
ConstraintViolationListInterface $violations)
{
if (null === $theUser) {
throw new NotFoundHttpException();
}
if (empty($modifiedUser->getPassword())) {
$modifiedUser->setPassword(null);
}
if (count($violations) > 0) {
$message = 'The user is not valid: ';
foreach ($violations as $violation) {
$message .= sprintf(
"Field %s: %s",
$violation->getPropertyPath(),
$violation->getMessage()
);
}
throw new ResourceValidationException($message);
}
$this->entityMerger->merge($theUser, $modifiedUser);
$this->encodePassword($theUser);
$this->persistUser($theUser);
return $theUser;
}
/**
* #param User $user
*/
protected function encodePassword(User $user): void
{
$user->setPassword(
$this->passwordEncoder->encodePassword(
$user,
$user->getPassword()
)
);
}
/**
* #param User $user
*/
protected function persistUser(User $user): void
{
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
}
}
My EntityMerger:
namespace AppBundle\Entity;
use Doctrine\Common\Annotations\Reader as AnnotationReader;
use Doctrine\ORM\Mapping\Id;
class EntityMerger
{
/**
* #var AnnotationReader
*/
private $annotationReader;
public function __construct(AnnotationReader $annotationReader)
{
$this->annotationReader = $annotationReader;
}
/**
* #param $entity
* #param $changes
*/
public function merge($entity, $changes)
{
$entityClassName = get_class($entity);
if (false === $entityClassName) {
throw new \InvalidArgumentException('$entity is not a class');
}
$changesClassName = get_class($changes);
if (false == $changesClassName) {
throw new \InvalidArgumentException('$entity is not a class');
}
if (!is_a($changes, $entityClassName)) {
throw new \InvalidArgumentException("Cannot merge object of class $changesClassName with object of class $entityClassName");
}
$entityReflection = new \ReflectionObject($entity);
$changesReflection = new \ReflectionObject($changes);
foreach ($changesReflection->getProperties() as $changedProperty) {
$changedProperty->setAccessible(true);
$changedPropertyValue = $changedProperty->getValue($changes);
if(null === $changedPropertyValue) {
continue;
}
if (!$entityReflection->hasProperty($changedProperty->getName())) {
continue;
}
$entityProperty = $entityReflection->getProperty($changedProperty->getName());
$annotation = $this->annotationReader->getPropertyAnnotation($entityProperty, Id::class);
if (null !== $annotation) {
continue;
}
$entityProperty->setAccessible(true);
$entityProperty->setValue($entity, $changedPropertyValue);
}
}
}

The message correctly states that you are not returning a response object.
From the manual, The only requirement for a controller is to return a Response object
If you want to return an object you could return JSON:
return $this->json(['user' => $theUser]);
This is just a guess from your code, because your question does not state what you want to return.

Related

Lumen API custom error message when route not found

Is it possible to have a custom error message on Lumen when a specific route not found is made? On default it will output the 'NotFoundHttpException' page. On Laravel it's possible, not sure how to do it on Lumen. Thanks
You need to edit render() function for handling not found inside app/Exceptions/Handler.php with code given below.
<?php
namespace App\Exceptions;
use Throwable;
use Illuminate\Http\Response;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Validation\ValidationException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* #var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* #param \Throwable $exception
* #return void
*
* #throws \Exception
*/
public function report(Throwable $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Throwable $exception
* #return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
*
* #throws \Throwable
*/
public function render($request, Throwable $exception)
{
$rendered = parent::render($request, $exception);
if ($exception instanceof NotFoundHttpException) {
//You can do any change as per your requrement here for the not found exception
$message = $exception->getMessage() ? $exception->getMessage() : Response::$statusTexts[$rendered->getStatusCode()];
$exception = new NotFoundHttpException($message, $exception);
} elseif ($exception instanceof HttpException) {
$message = $exception->getMessage() ? $exception->getMessage() : Response::$statusTexts[$rendered->getStatusCode()];
$exception = new HttpException($rendered->getStatusCode(), $message);
} else {
$statusCode = Response::HTTP_INTERNAL_SERVER_ERROR;
$message = env('APP_DEBUG', false) ? $exception->getMessage() : Response::$statusTexts[$statusCode];
$exception = new HttpException($statusCode, $message);
}
// Resonse
return response()->json([
'meta' => [
'code' => $rendered->getStatusCode(),
'message' => $exception->getMessage()
]
], $rendered->getStatusCode());
}
}

Too many Redirects with Controller

When I try to define my routes with an ImagesController, I get a "site redirected you too many times" error when going to what should be the index. I'm stumped. Am I over-tired and not seeing something obvious?
web.php
Route::prefix('images')->group(function(){
Route::post('add-tag', 'ImagesController#addTag');
Route::get('test', 'ImagesController#index');
});
When I access /images/test, the controller responds correctly. When I have it defined as '' or / it redirects too much. I'm not setting them simultaneously.
Route::prefix('images')->group(function(){
Route::post('add-tag', 'ImagesController#addTag');
// like this:
Route::get('', 'ImagesController#index');
// or like the following:
Route::get('/', 'ImagesController#index');
});
I've even tried to define /images before the prefix group to no avail. images/test is fine in this case.
Route::get('images', 'ImagesController#index');
Route::prefix('images')->group(function(){
Route::post('add-tag', 'ImagesController#addTag');
Route::get('test', 'ImagesController#index');
});
ImagesController.php
namespace App\Http\Controllers;
use \Auth;
use App\Helpers;
use App\Image;
use App\Tag;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Console\Helper\Helper;
class ImagesController extends Controller
{
private $sortBy = [
'created_at',
'updated_at',
'orig_name',
'orig_size'
];
private $defaultSortBy = 'created_at';
private $defaultOrder = 'desc';
/**
* #param Request $request
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(Request $request)
{
$sort = $request->get('sort', $this->defaultSortBy);
$sort = in_array($sort, $this->sortBy) ? $sort : 'created_at';
$order = $request->get('order', $this->defaultOrder);
$order = $order == 'desc' ? 'desc' : 'asc';
$images = Image::orderBy($sort, $order)
->whereQuestionable(0)
->wherePrivate(0)
->paginate(config('image.images_per_page'));
if ($images !== null && $sort !== $this->defaultSortBy) {
$images->appends(['sort' => $sort]);
}
if ($images !== null && $order !== $this->defaultOrder) {
$images->appends(['order' => $order]);
}
return view(
'images.index',
[
'images' => $images,
'sort' => $sort,
'order' => $order
]
);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
//this function works correctly, but I suppose it may be interfering?
public function addTag(Request $request)
{
Log::debug(print_r($request->all(), true));
$error = '';
$uid = trim($request->input('uid', ''));
$newTag = Helpers::prepTag($request->input('tag', ''));
if (!Auth::check()){
$error .= 'You can only add tags to images if you are logged in.';
} else if ($uid === '' || $newTag === '') {
$error .= 'UID and tag cannot be empty';
} else {
$image = Image::whereUid($uid)->unQuestionable()->first();
$currentTags = [];
if (count($image->tags)){
foreach ($image->tags as $currentTag) {
$currentTags[$currentTag->id] = $currentTag->tag;
}
}
if ($image === null) {
$error .= "Image $uid was not found.";
} else {
$tag = Tag::firstOrNew(['tag'=>$newTag]);
if ($tag->ip == '') {
$tag->ip = $request->getClientIp();
$tag->user_id = Auth::check() ? Auth::user()->id : 5;
$tag->save();
}
//\Log::info(print_r($currentTags, true));
//\Log::info(print_r($tag, true));
$addTag = !(bool)isset($currentTags[$tag->id]);
$image->tags()->sync([$tag->id], false);
}
}
if ($request->ajax()) {
if ($error !== '') {
return response()->json(['message' => $error],400);
}
return response()->json(['tagId' => $tag->id, 'imageUid' => $image->uid, 'tag' => $tag->tag, 'isAdmin' => true, 'addTag' => $addTag]);
} else {
if ($error !== '') {
Helpers::alert(3, $error, 'Tag Not Added');
}
return redirect('/');
}
}
}
As I have a model named Images implicit binding was interfering with my defined routes for a controller with the name ImagesController, and applying the prefix /images. After changing the name in the routing to image this issue went away.

MimeMailParser put message part together

i'm building a small interface that pipe messages from postfix via stdin, and want to remove attachments from email/ anyway, i don't want to remove all the attachments, just those who are too big to be emailed.
i found MimeMailParser as a good point of start and made a few modifications to it's code (made some private methods public, in order to call them seperatley). here is the class in my version:
<?php
require_once('attachment.class.php');
/**
* Fast Mime Mail parser Class using PHP's MailParse Extension
* #author gabe#fijiwebdesign.com
* #url http://www.fijiwebdesign.com/
* #license http://creativecommons.org/licenses/by-sa/3.0/us/
* #version $Id$
*/
class MimeMailParser {
/**
* PHP MimeParser Resource ID
*/
public $resource;
/**
* A file pointer to email
*/
public $stream;
/**
* A text of an email
*/
public $data;
/**
* Stream Resources for Attachments
*/
public $attachment_streams;
public $parts;
/**
* Inialize some stuff
* #return
*/
public function __construct() {
$this->attachment_streams = array();
}
/**
* Free the held resouces
* #return void
*/
public function __destruct() {
// clear the email file resource
if (is_resource($this->stream)) {
fclose($this->stream);
}
// clear the MailParse resource
if (is_resource($this->resource)) {
mailparse_msg_free($this->resource);
}
// remove attachment resources
foreach($this->attachment_streams as $stream) {
fclose($stream);
}
}
/**
* Set the file path we use to get the email text
* #return Object MimeMailParser Instance
* #param $mail_path Object
*/
public function setPath($path) {
// should parse message incrementally from file
$this->resource = mailparse_msg_parse_file($path);
$this->stream = fopen($path, 'r');
$this->parse();
return $this;
}
/**
* Set the Stream resource we use to get the email text
* #return Object MimeMailParser Instance
* #param $stream Resource
*/
public function setStream($stream) {
// streams have to be cached to file first
if (get_resource_type($stream) == 'stream') {
$tmp_fp = tmpfile();
if ($tmp_fp) {
while(!feof($stream)) {
fwrite($tmp_fp, fread($stream, 2028));
}
fseek($tmp_fp, 0);
$this->stream =& $tmp_fp;
} else {
throw new Exception('Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.');
return false;
}
fclose($stream);
} else {
$this->stream = $stream;
}
$this->resource = mailparse_msg_create();
// parses the message incrementally low memory usage but slower
while(!feof($this->stream)) {
mailparse_msg_parse($this->resource, fread($this->stream, 2082));
}
$this->parse();
return $this;
}
/**
* Set the email text
* #return Object MimeMailParser Instance
* #param $data String
*/
public function setText($data) {
$this->resource = mailparse_msg_create();
// does not parse incrementally, fast memory hog might explode
mailparse_msg_parse($this->resource, $data);
$this->data = $data;
$this->parse();
return $this;
}
/**
* Parse the Message into parts
* #return void
* #private
*/
private function parse() {
$structure = mailparse_msg_get_structure($this->resource);
$this->parts = array();
foreach($structure as $part_id) {
$part = mailparse_msg_get_part($this->resource, $part_id);
$this->parts[$part_id] = mailparse_msg_get_part_data($part);
}
}
/**
* Retrieve the Email Headers
* #return Array
*/
public function getHeaders() {
if (isset($this->parts[1])) {
return $this->getPartHeaders($this->parts[1]);
} else {
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
}
return false;
}
/**
* Retrieve the raw Email Headers
* #return string
*/
public function getHeadersRaw() {
if (isset($this->parts[1])) {
return $this->getPartHeaderRaw($this->parts[1]);
} else {
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
}
return false;
}
/**
* Retrieve a specific Email Header
* #return String
* #param $name String Header name
*/
public function getHeader($name) {
if (isset($this->parts[1])) {
$headers = $this->getPartHeaders($this->parts[1]);
if (isset($headers[$name])) {
return $headers[$name];
}
} else {
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email headers.');
}
return false;
}
/**
* Returns the email message body in the specified format
* #return Mixed String Body or False if not found
* #param $type Object[optional]
*/
public function getMessageBody($type = 'text') {
$body = false;
$mime_types = array(
'text'=> 'text/plain',
'html'=> 'text/html'
);
if (in_array($type, array_keys($mime_types))) {
foreach($this->parts as $part) {
if ($this->getPartContentType($part) == $mime_types[$type]) {
$headers = $this->getPartHeaders($part);
$body = $this->getPartBody($part);
break;
}
}
} else {
throw new Exception('Invalid type specified for MimeMailParser::getMessageBody. "type" can either be text or html.');
}
return $body;
}
/**
* get the headers for the message body part.
* #return Array
* #param $type Object[optional]
*/
public function getMessageBodyHeaders($type = 'text') {
$headers = false;
$mime_types = array(
'text'=> 'text/plain',
'html'=> 'text/html'
);
if (in_array($type, array_keys($mime_types))) {
foreach($this->parts as $part) {
if ($this->getPartContentType($part) == $mime_types[$type]) {
$headers = $this->getPartHeaders($part);
break;
}
}
} else {
throw new Exception('Invalid type specified for MimeMailParser::getMessageBody. "type" can either be text or html.');
}
return $headers;
}
/**
* Returns inline content files.
* #return Array
*/
public function getInlineContent() {
$content = array();
foreach($this->parts as $part) {
$content_id = $this->getPartContentId($part);
if ($content_id !== FALSE) {
$content[] = new MimeMailParser_attachment(
$this->getPartContentName($part),
$this->getPartContentType($part),
$this->getAttachmentStream($part),
$this->getPartContentDisposition($part),
$this->getPartHeaders($part)
);
}
}
return $content;
}
/**
* Returns the attachments contents in order of appearance
* #return Array
* #param $type Object[optional]
*/
public function getAttachments() {
$attachments = array();
$dispositions = array("attachment","inline");
foreach($this->parts as $part) {
$disposition = $this->getPartContentDisposition($part);
if (in_array($disposition, $dispositions) === TRUE) {
if (isset($part['disposition-filename']) === FALSE) {
$part['disposition-filename'] = md5(uniqid());
}
$attachments[] = new MimeMailParser_attachment(
$part['disposition-filename'],
$this->getPartContentType($part),
$this->getAttachmentStream($part),
$disposition,
$this->getPartHeaders($part)
);
}
}
return $attachments;
}
/**
* Return the Headers for a MIME part
* #return Array
* #param $part Array
*/
private function getPartHeaders($part) {
if (isset($part['headers'])) {
return $part['headers'];
}
return false;
}
/**
* Return a Specific Header for a MIME part
* #return Array
* #param $part Array
* #param $header String Header Name
*/
private function getPartHeader($part, $header) {
if (isset($part['headers'][$header])) {
return $part['headers'][$header];
}
return false;
}
/**
* Return the ContentType of the MIME part
* #return String
* #param $part Array
*/
private function getPartContentType($part) {
if (isset($part['content-type'])) {
return $part['content-type'];
}
return false;
}
/**
* Return the ContentName of the MIME part
* #return String
* #param $part Array
*/
private function getPartContentName($part) {
if (isset($part['content-name'])) {
return $part['content-name'];
}
return false;
}
/**
* Return the Content Disposition
* #return String
* #param $part Array
*/
private function getPartContentDisposition($part) {
if (isset($part['content-disposition'])) {
return $part['content-disposition'];
}
return false;
}
/**
* Return the Content id
* #return String
* #param $part Array
*/
private function getPartContentId($part) {
if (isset($part['content-id'])) {
return $part['content-id'];
}
return false;
}
/**
* Retrieve the raw Header of a MIME part
* #return String
* #param $part Object
*/
private function getPartHeaderRaw(&$part) {
$header = '';
if ($this->stream) {
$header = $this->getPartHeaderFromFile($part);
} else if ($this->data) {
$header = $this->getPartHeaderFromText($part);
} else {
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email parts.');
}
return $header;
}
/**
* Retrieve the Body of a MIME part
* #return String
* #param $part Object
*/
private function getPartBody(&$part) {
$body = '';
if ($this->stream) {
$body = $this->getPartBodyFromFile($part);
} else if ($this->data) {
$body = $this->getPartBodyFromText($part);
} else {
throw new Exception('MimeMailParser::setPath() or MimeMailParser::setText() must be called before retrieving email parts.');
}
return $body;
}
/**
* Retrieve the Header from a MIME part from file
* #return String Mime Header Part
* #param $part Array
*/
private function getPartHeaderFromFile(&$part) {
$start = $part['starting-pos'];
$end = $part['starting-pos-body'];
fseek($this->stream, $start, SEEK_SET);
$header = fread($this->stream, $end-$start);
return $header;
}
/**
* Retrieve the Body from a MIME part from file
* #return String Mime Body Part
* #param $part Array
*/
private function getPartBodyFromFile(&$part) {
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
fseek($this->stream, $start, SEEK_SET);
$body = fread($this->stream, $end-$start);
return $body;
}
/**
* Retrieve the Header from a MIME part from text
* #return String Mime Header Part
* #param $part Array
*/
public function getPartHeaderFromText(&$part) {
$start = $part['starting-pos'];
$end = $part['starting-pos-body'];
$header = substr($this->data, $start, $end-$start);
return $header;
}
/**
* Retrieve the Body from a MIME part from text
* #return String Mime Body Part
* #param $part Array
*/
public function getPartBodyFromText(&$part) {
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
$body = substr($this->data, $start, $end-$start);
return $body;
}
/**
* Read the attachment Body and save temporary file resource
* #return String Mime Body Part
* #param $part Array
*/
private function getAttachmentStream(&$part) {
$temp_fp = tmpfile();
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
if ($temp_fp) {
if ($this->stream) {
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
fseek($this->stream, $start, SEEK_SET);
$len = $end-$start;
$written = 0;
$write = 2028;
$body = '';
while($written < $len) {
if (($written+$write < $len )) {
$write = $len - $written;
}
$part = fread($this->stream, $write);
fwrite($temp_fp, $this->decode($part, $encoding));
$written += $write;
}
} else if ($this->data) {
$attachment = $this->decode($this->getPartBodyFromText($part), $encoding);
fwrite($temp_fp, $attachment, strlen($attachment));
}
fseek($temp_fp, 0, SEEK_SET);
} else {
throw new Exception('Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.');
return false;
}
return $temp_fp;
}
/**
* Decode the string depending on encoding type.
* #return String the decoded string.
* #param $encodedString The string in its original encoded state.
* #param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
*/
public function decode($encodedString, $encodingType) {
if (strtolower($encodingType) == 'base64') {
return base64_decode($encodedString);
} else if (strtolower($encodingType) == 'quoted-printable') {
return quoted_printable_decode($encodedString);
} else {
return $encodedString;
}
}
}
?>
i call the code and use it as follows:
<?php
ini_set("display_errors","on");
error_reporting(E_ALL);
require_once('MimeMailParser.class.php');
$Parser = new MimeMailParser();
$Parser->setText(file_get_contents('php://stdin'));
$attachments = $Parser->getAttachments();
/*foreach($attachments as $attachment) {
echo $attachment->filename;
}*/
echo $Parser->getHeadersRaw(); # print email header
foreach ($Parser->parts as $xPart=>$yPart) {
if ($xPart=='1') {
continue;
}
echo $Parser->getPartHeaderFromText($yPart);
echo $Parser->getPartBodyFromText($yPart);
}
?>
that sends the message and all of the conetnts appears ok - beside one issue - attachments are not displayed. although, when i click "show original" the attachments as base64 encoded does appear on the message source.
any idea?

How to resize uploaded image in zend framework

I have a form with upload image field. How to resize the recently uploaded image to desired size?
My current form is :
<?php
class Application_Form_User extends Zend_Form
{
public function init()
{
$this->setAttrib('enctype', 'multipart/form-data');
$this->setAction("");
$this->setMethod("post");
$element = new Zend_Form_Element_File('photo');
$element->setLabel('Upload an image:')
->setValueDisabled(true);
$this->addElement($element, 'photo');
$element->addValidator('Count', false, 1);
// limit to 1000K
$element->addValidator('Size', false, 1024000);
// only JPEG, PNG, and GIFs
$element->addValidator('Extension', false, 'jpg,png,gif');
$submit = $this->createElement('submit', 'submit');
$submit->setLabel('Save');
$this->addElement($submit);
}
}
And my controller:
public function indexAction()
{
$form=new Application_Form_User();
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$file=pathinfo($form->photo->getFileName());
$form->photo->addFilter('Rename', PUBLIC_PATH.'/images/'.uniqid().time().'.'.$file['extension']);
if ($form->photo->receive()) {
$this->view->photo=pathinfo($form->photo->getFileName());
}
}
}
$this->view->form=$form;
}
Can somebody provide me with an example? How can i use plugins like php thumbnailer or similar plugin to resize the uploaded image?
Skoch_Filter_File_Resize works. It is a custom filter: http://eliteinformatiker.de/2011/09/02/thumbnails-upload-and-resize-images-with-zend_form_element_file/
<?php
// Skoch/Filter/File/Resize.php
/**
* Zend Framework addition by skoch
*
* #category Skoch
* #package Skoch_Filter
* #license http://opensource.org/licenses/gpl-license.php GNU Public License
* #author Stefan Koch <cct#stefan-koch.name>
*/
/**
* #see Zend_Filter_Interface
*/
require_once 'Zend/Filter/Interface.php';
/**
* Resizes a given file and saves the created file
*
* #category Skoch
* #package Skoch_Filter
*/
class Skoch_Filter_File_Resize implements Zend_Filter_Interface
{
protected $_width = null;
protected $_height = null;
protected $_keepRatio = true;
protected $_keepSmaller = true;
protected $_directory = null;
protected $_adapter = 'Skoch_Filter_File_Resize_Adapter_Gd';
/**
* Create a new resize filter with the given options
*
* #param Zend_Config|array $options Some options. You may specify: width,
* height, keepRatio, keepSmaller (do not resize image if it is smaller than
* expected), directory (save thumbnail to another directory),
* adapter (the name or an instance of the desired adapter)
* #return Skoch_Filter_File_Resize An instance of this filter
*/
public function __construct($options = array())
{
if ($options instanceof Zend_Config) {
$options = $options->toArray();
} elseif (!is_array($options)) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('Invalid options argument provided to filter');
}
if (!isset($options['width']) && !isset($options['height'])) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('At least one of width or height must be defined');
}
if (isset($options['width'])) {
$this->_width = $options['width'];
}
if (isset($options['height'])) {
$this->_height = $options['height'];
}
if (isset($options['keepRatio'])) {
$this->_keepRatio = $options['keepRatio'];
}
if (isset($options['keepSmaller'])) {
$this->_keepSmaller = $options['keepSmaller'];
}
if (isset($options['directory'])) {
$this->_directory = $options['directory'];
}
if (isset($options['adapter'])) {
if ($options['adapter'] instanceof Skoch_Filter_File_Resize_Adapter_Abstract) {
$this->_adapter = $options['adapter'];
} else {
$name = $options['adapter'];
if (substr($name, 0, 33) != 'Skoch_Filter_File_Resize_Adapter_') {
$name = 'Skoch_Filter_File_Resize_Adapter_' . ucfirst(strtolower($name));
}
$this->_adapter = $name;
}
}
$this->_prepareAdapter();
}
/**
* Instantiate the adapter if it is not already an instance
*
* #return void
*/
protected function _prepareAdapter()
{
if ($this->_adapter instanceof Skoch_Filter_File_Resize_Adapter_Abstract) {
return;
} else {
$this->_adapter = new $this->_adapter();
}
}
/**
* Defined by Zend_Filter_Interface
*
* Resizes the file $value according to the defined settings
*
* #param string $value Full path of file to change
* #return string The filename which has been set, or false when there were errors
*/
public function filter($value)
{
if ($this->_directory) {
$target = $this->_directory . '/' . basename($value);
} else {
$target = $value;
}
return $this->_adapter->resize($this->_width, $this->_height,
$this->_keepRatio, $value, $target, $this->_keepSmaller);
}
}
<?php
// Skoch/Filter/File/Resize/Adapter/Abstract.php
/**
* Zend Framework addition by skoch
*
* #category Skoch
* #package Skoch_Filter
* #license http://opensource.org/licenses/gpl-license.php GNU Public License
* #author Stefan Koch <cct#stefan-koch.name>
*/
/**
* Resizes a given file and saves the created file
*
* #category Skoch
* #package Skoch_Filter
*/
abstract class Skoch_Filter_File_Resize_Adapter_Abstract
{
abstract public function resize($width, $height, $keepRatio, $file, $target, $keepSmaller = true);
protected function _calculateWidth($oldWidth, $oldHeight, $width, $height)
{
// now we need the resize factor
// use the bigger one of both and apply them on both
$factor = max(($oldWidth/$width), ($oldHeight/$height));
return array($oldWidth/$factor, $oldHeight/$factor);
}
}
<?php
// Skoch/Filter/File/Resize/Adapter/Gd.php
/**
* Zend Framework addition by skoch
*
* #category Skoch
* #package Skoch_Filter
* #license http://opensource.org/licenses/gpl-license.php GNU Public License
* #author Stefan Koch <cct#stefan-koch.name>
*/
require_once 'Skoch/Filter/File/Resize/Adapter/Abstract.php';
/**
* Resizes a given file with the gd adapter and saves the created file
*
* #category Skoch
* #package Skoch_Filter
*/
class Skoch_Filter_File_Resize_Adapter_Gd extends
Skoch_Filter_File_Resize_Adapter_Abstract
{
public function resize($width, $height, $keepRatio, $file, $target, $keepSmaller = true)
{
list($oldWidth, $oldHeight, $type) = getimagesize($file);
switch ($type) {
case IMAGETYPE_PNG:
$source = imagecreatefrompng($file);
break;
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($file);
break;
case IMAGETYPE_GIF:
$source = imagecreatefromgif($file);
break;
}
if (!$keepSmaller || $oldWidth > $width || $oldHeight > $height) {
if ($keepRatio) {
list($width, $height) = $this->_calculateWidth($oldWidth, $oldHeight, $width, $height);
}
} else {
$width = $oldWidth;
$height = $oldHeight;
}
$thumb = imagecreatetruecolor($width, $height);
imagealphablending($thumb, false);
imagesavealpha($thumb, true);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $width, $height, $oldWidth, $oldHeight);
switch ($type) {
case IMAGETYPE_PNG:
imagepng($thumb, $target);
break;
case IMAGETYPE_JPEG:
imagejpeg($thumb, $target);
break;
case IMAGETYPE_GIF:
imagegif($thumb, $target);
break;
}
return $target;
}
}
$photo->addFilter(new Skoch_Filter_File_Resize(array(
'width' => 200,
'height' => 300,
'keepRatio' => true,
)));

PHPUnit Zend_Test_PHPUnit_DatabaseTestCase fails to truncate table

I am setting up some db integration testing using Zend_Test_PHPUnit_DatabaseTestCase.
My tests run but the db tables do not get truncated so an add test fails assertion - as the xml I provide as a dataset does not match the db can anybody suggest why
TestCase
class ArtworkDBTest extends DatabaseTestCase
{
public function testAddArtwork()
{
$data=array("artwork_name"=>'test',"description"=>'test',"imgpath"=>'test',"size"=>'test',"price_information"=>'test',"category"=>1,"artwork_order"=>1);
$mockedLog=$this->getMock("Log",array("log"));
$artwork = new shop_Artwork($mockedLog,Zend_Db_Table_Abstract::getDefaultAdapter());
$artwork->addArtwork($data);
$this->assertDataSetsMatchXML('artwork-add.xml', $dataSet);
}
}
Database testing setup code (adapted from dragonbe and ibuildings tutorials)
abstract class DatabaseTestCase extends Zend_Test_PHPUnit_DatabaseTestCase
{
const DEFAULT_CONNECTION_SCHEMA = 'main';
protected $_connectionMock;
private $__configuration = NULL;
protected $_connectionSchema = self::DEFAULT_CONNECTION_SCHEMA;
protected $_seedFilesPath;
protected $dataSet;
public function __construct()
{
$this->dataSet = new Zend_Test_PHPUnit_Db_DataSet_QueryDataSet($this->getConnection());
$this->dataSet->addTable('artwork','Select* from artwork');
$this->dataSet->addTable('login','Select *from login');
$this->dataSet->addTable('category','Select *from category');
}
public function getConfiguration()
{
if ($this->__configuration == NULL) {
$this->__configuration = new Zend_Config_Ini(TEST_PATH . '/application/configs/tests.ini');
}
return $this->__configuration;
}
public function getSeedFilesPath()
{
if ($this->_seedFilesPath == NULL) {
$this->_seedFilesPath = $this->getConfiguration()->tests->seeds->folder;
}
return rtrim($this->_seedFilesPath, '/') . '/';
}
protected function getConnection()
{
if ($this->_connectionMock == NULL) {
$dbAdapterName = $this->getConfiguration()->tests->dbadapter;
$dbAdapterParams = $this->getConfiguration()->tests->dbparams->toArray();
$connection = Zend_Db::factory($dbAdapterName, $dbAdapterParams);
$this->_connectionMock = $this->createZendDbConnection(
$connection, $this->_connectionSchema
);
Zend_Db_Table_Abstract::setDefaultAdapter($connection);
}
return $this->_connectionMock;
}
protected function getDataSet()
{
return $this->createFlatXMLDataSet(TEST_PATH . '/fixtures/models/artwork-seed.xml');
}
/**
* Convert a Rowset to a Dataset
*
* #param Zend_Db_Table_Rowset_Abstract $rowset
* #param string $tableName
* #return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
*/
public function convertRowsetToDataSet($rowset, $tableName = NULL)
{
$rowsetDataSet = new Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset, $tableName);
return new PHPUnit_Extensions_Database_DataSet_DefaultDataSet(array($rowsetDataSet));
}
/**
* Convert a Record to a Dataset
*
* #param array $data
* #param string $tableName
* #return PHPUnit_Extensions_Database_DataSet_DefaultDataSet
*/
public function convertRecordToDataSet(Array $data, $tableName)
{
$rowset = new Zend_Db_Table_Rowset(array('data' => array($data)));
return $this->convertRowsetToDataSet($rowset, $tableName);
}
/**
* Compare dataset with data stored in the file
*
* #param string $filename
* #param PHPUnit_Extensions_Database_DataSet_IDataSet $expected
* #return boolean
*/
public function assertDataSetsMatchXML($filename, PHPUnit_Extensions_Database_DataSet_IDataSet $actual)
{
if (empty($filename) || !is_string($filename))
throw new InvalidArgumentException(
'Second parameter "filename" is not a valid string.'
);
$expected = $this->createFlatXmlDataSet($this->getSeedFilesPath() . $filename);
return $this->assertDataSetsEqual($expected, $actual);
}
}
The answer was running parent::setUp(); inside the test class's setUp() method