I wish to retrieve all sellers items using the findItemsAdvanced call of Zend_Service_Ebay_Finding API. I'm a bit confused as to how to use it? has anyone got a example of how this method works? I tried
$response = $finding->findItemsAdvanced('seller=<SELLERNAME>');
But gives me nothing?
Would appreciate any help
In the end I overloaded the Zend_Service_Ebay_Finding API and added 2 methods to grab me all the seller info. Maybe this will help anyone else with the same issue.
/**
* Finds items for a specific seller
* and a page
*
* #param string $seller
* #param int $page
* #return Zend_Service_Ebay_Finding_Response_Items
*/
public function sellerItems($seller, $page = 1){
// prepare options
$options = array('itemFilter(0).name' => 'Seller', 'itemFilter(0).value(0)' => $seller, 'paginationInput.entriesPerPage' => 100);
// do request
return $this->_findItems($options, 'findItemsAdvanced');
}
/**
* Finds items for a specific seller - iterates through pages
* and a page
*
* #param string $seller
* #return array
*/
public function getAllSellerItems($seller) {
$page1 = $this->sellerItems($seller);
$pages = $page1->paginationOutput->totalPages;
$items = $page1->searchResult->item;
$full = array();
foreach($items as $item) {
$full[] = $item;
}
if($pages > 1) {
for($i = 2;$i <= $pages; $i ++) {
$results = $this->sellerItems($seller, $i);
$items = $results->searchResult->item;
foreach($items as $item) {
$full[] = $item;
}
}
}
return $full;
}
Related
I am trying to fetch all child product Ids from configurable product Ids.
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->create('\Magento\Catalog\Model\Product');
$storeManager = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface');
$currentStore = $storeManager->getStore();
$mediaUrl = $currentStore->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$productURL = $mediaUrl.'catalog/product';
$collection = $this->_productCollectionFactory->create();
$productCollection = $collection->addAttributeToSelect('*')->addAttributeToFilter('type_id','configurable');
$vendor_product = array();
$productData = $product->getData();
foreach($productCollection as $prodObj){
$productData = array();
$product = $product->load($prodObj->getId());
$productTypeInstance = $product->getTypeInstance();
$usedProducts = $productTypeInstance->getUsedProducts($product);
foreach ($usedProducts as $child) {
$productData['childrenIds'][] = $child->getId();
}
I get Ids of my first configurable product in all the cases
<?php
namespace Vendor\Module\Block;
class ParentAndChilds extends \Magento\Framework\View\Element\Template
{
/**
* #var Context
*/
protected $context;
/**
* #var ProductRepositoryInterface
*/
protected $productRepository;
/**
* #var SearchCriteriaBuilder
*/
protected $searchCriteriaBuilder;
/**
* #var LinkManagementInterface
*/
protected $linkManagement;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\ConfigurableProduct\Api\LinkManagementInterface $linkManagement,
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
array $data = []
)
{
$this->linkManagement = $linkManagement;
$this->productRepository = $productRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
parent::__construct($context, $data);
}
public function getParentsAndChilds()
{
$searchCriteria = $this->searchCriteriaBuilder
->addFilter('type_id', 'configurable')
->create();
$configurableProducts = $this->productRepository
->getList($searchCriteria);
$parentAndChildProducts = array();
foreach ($configurableProducts->getItems() as $configurableProduct) {
$childProducts = $this->linkManagement
->getChildren($configurableProduct->getSku());
foreach ($childProducts as $childProduct) {
$parentAndChildProducts[$configurableProduct->getId()][] = $childProduct->getId();
}
}
return $parentAndChildProducts;
}
}
To get child product Ids from a configurable product, you can use below code:
public function __construct(
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository
) {
$this->productRepository = $productRepository;
}
public function execute()
{
$_productId=57786;
$_product=$this->productRepository->getById($_productId);
$childIs=$_product->getExtensionAttributes()->getConfigurableProductLinks();
print_r($childIs);
}
Output looks like:
Array
(
[31981] => 31981
[31982] => 31982
[31983] => 31983
)
Hope it will help you.
$_children = $_product->getTypeInstance()->getUsedProducts($_product);
foreach ($_children as $child){
$childProducts[] = $child;
}
$_product is the configurable product object
You can use the below code for getting Child ID.
$product = $block->getProduct();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$configurable_product_id = $product->getId();
$configurableProduct = $objectManager->get('Magento\Catalog\Model\ProductRepository')->getById($configurable_product_id);
$children = $configurableProduct->getTypeInstance()->getUsedProducts($configurableProduct); $childIds = array();
foreach ($children as $child){
$childIds[] = $child->getId();
}
sort($childIds);
print_r($childIds);
This is for sample code but I suggest do not use $objectManager directly, you can use Block on Plugin Method to get Product Object.
To get all simple children including out of stock products use:
$children = $product
->getTypeInstance()
->getChildrenIds($product->getId());
print_r($children);
thanks for reading and answering...
I have some TYPO3 gridelements in my TYPO3 pagecontent.
Each gridelement has a tab "appearance", where I define an image file.
The database relation from tt_content to the media image are in sys_file_reference.
My question is how can I get this image file in my fluid template by using the ViewHelper and the uid of my gridelement?
I wrote an little ViewHelper (tested on 7.6, but should not need so much changes for 8.7) to get referenced images for an newsletter layout:
<?php
namespace Vendor\Extension\ViewHelpers;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Resource\FileRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Resource\Exception;
use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3\CMS\Fluid\Core\ViewHelper\Facets\CompilableInterface;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
class ImagesReferencesViewHelper extends AbstractViewHelper implements CompilableInterface
{
/**
* Iterates through elements of $each and renders child nodes
*
* #param int $uid The ID of the element
* #param string $table The Referenced table name
* #param string $fieldName The Referenced field name
* #param string $as The name of the iteration variable
* #param string $key The name of the variable to store the current array key
* #param boolean $reverse If enabled, the iterator will start with the last element and proceed reversely
* #param string $iteration The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)
* #param string $link The name of the variable to store link
*
* #return string Rendered string
* #api
*/
public function render($uid, $table = 'tt_content', $fieldName = 'assets', $as, $key = '', $reverse = false, $iteration = null, $link = null)
{
return self::renderStatic($this->arguments, $this->buildRenderChildrenClosure(), $this->renderingContext);
}
/**
* #param array $arguments
* #param \Closure $renderChildrenClosure
* #param \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext
*
* #return string
* #throws \TYPO3\CMS\Fluid\Core\ViewHelper\Exception
*/
static public function renderStatic(array $arguments, \Closure $renderChildrenClosure, \TYPO3\CMS\Fluid\Core\Rendering\RenderingContextInterface $renderingContext)
{
$templateVariableContainer = $renderingContext->getTemplateVariableContainer();
if ($arguments['uid'] === null || $arguments['table'] === null || $arguments['fieldName'] === null) {
return '';
}
/** #var FileRepository $fileRepository */
$fileRepository = GeneralUtility::makeInstance(FileRepository::class);
$images = array();
try {
$images = $fileRepository->findByRelation($arguments['table'], $arguments['fieldName'], $arguments['uid']);
} catch (Exception $e) {
/** #var \TYPO3\CMS\Core\Log\Logger $logger */
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger();
$logger->warning('The file-reference with uid "' . $arguments['uid'] . '" could not be found and won\'t be included in frontend output');
}
if (is_object($images) && !$images instanceof \Traversable) {
throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('ImagesReferencesViewHelper only supports arrays and objects implementing \Traversable interface', 1248728393);
}
if ($arguments['reverse'] === true) {
// array_reverse only supports arrays
if (is_object($images)) {
$images = iterator_to_array($images);
}
$images = array_reverse($images);
}
$iterationData = array(
'index' => 0,
'cycle' => 1,
'total' => count($images)
);
$output = '';
foreach ($images as $keyValue => $singleElement) {
$templateVariableContainer->add($arguments['as'], $singleElement);
/** #var FileReference $singleElement */
if ($arguments['link'] !== null && $singleElement->getLink()) {
$link = $singleElement->getLink();
/** #var ContentObjectRenderer $contentObject */
$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$newLink = $contentObject->typoLink_URL(array('parameter' => $link));
$templateVariableContainer->add($arguments['link'], $newLink);
}
if ($arguments['key'] !== '') {
$templateVariableContainer->add($arguments['key'], $keyValue);
}
if ($arguments['iteration'] !== null) {
$iterationData['isFirst'] = $iterationData['cycle'] === 1;
$iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total'];
$iterationData['isEven'] = $iterationData['cycle'] % 2 === 0;
$iterationData['isOdd'] = !$iterationData['isEven'];
$templateVariableContainer->add($arguments['iteration'], $iterationData);
$iterationData['index']++;
$iterationData['cycle']++;
}
$output .= $renderChildrenClosure();
$templateVariableContainer->remove($arguments['as']);
if ($arguments['link'] !== null && $singleElement->getLink()) {
$templateVariableContainer->remove($arguments['link']);
}
if ($arguments['key'] !== '') {
$templateVariableContainer->remove($arguments['key']);
}
if ($arguments['iteration'] !== null) {
$templateVariableContainer->remove($arguments['iteration']);
}
}
return $output;
}
}
In my extension I'm using the Typo3 image manipulation. I would like to render the picture responsive with the srcset attribute. Therefore I'm using the VHS media.image viewhelper. The problem I have is that this viewhelper doesn't support the Typo3 native crop functionality. And the Fluid image viewhelper doesn't support the srcset functionality.
Is there a easy solution for this problem or do I need to write a custom viewhelper?
<f:image treatIdAsReference="true" src="{image.id}" alt="{image.alternative}" title="{image.title}" crop="{image.crop}" />
<v:media.image src="{image.id}" alt="{image.alternative}" title="{image.title}" srcset="480,768,992,1200" />
I'm happy for every help.
This feature is not yet implemented in VHS. I just created a pull request which can be found at https://github.com/FluidTYPO3/vhs/pull/1091/commits/761435c82786cf9da6626d849a39c6a9124bfdff.
Just override the related file and it should be fine!
I changed the SourceSetViewHelperTrait.php. Now the rendering is working. treatIdAsReference must be true otherwise the processed image will be used to create the srcset images.
<?php
namespace FluidTYPO3\Vhs\Traits;
use FluidTYPO3\Vhs\Utility\FrontendSimulationUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
/*
* This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/
/**
* This trait can be used by viewhelpers that generate image tags
* to add srcsets based to the imagetag for better responsiveness
*/
trait SourceSetViewHelperTrait
{
/**
* used to attach srcset variants of a given image to the specified tag
*
* #param \TYPO3\CMS\Fluid\Core\ViewHelper\TagBuilder $tag the tag to add the srcset as argument
* #param string $src image path to render srcsets for
* #return array
*/
public function addSourceSet($tag, $src)
{
$srcsets = $this->getSourceSetWidths();
if ('BE' === TYPO3_MODE) {
FrontendSimulationUtility::simulateFrontendEnvironment();
}
$width = $this->arguments['width'];
$height = $this->arguments['height'];
$format = $this->arguments['format'];
$quality = $this->arguments['quality'];
$dimensions = [
'ratio'=>0,
];
$treatIdAsReference = (boolean) $this->arguments['treatIdAsReference'];
if (true === $treatIdAsReference) {
$src = $this->arguments['src'];
$crop = $this->arguments['crop'];
if ($crop === null) {
$crop = $src instanceof FileReference ? $src->getProperty('crop') : null;
}
$dimensions = $this->getDimensions($width, $height);
}
$imageSources = [];
$srcsetVariants = [];
foreach ($srcsets as $key => $width) {
if (0 < $dimensions['ratio']) {
$height = floor((int)$width/$dimensions['ratio']) . $dimensions['postHeight'];
}
$width = $width . $dimensions['postWidth'];
$srcsetVariant = $this->getImgResource($src, $width, $height, $format, $quality, $treatIdAsReference, $crop);
$srcsetVariantSrc = rawurldecode($srcsetVariant[3]);
$srcsetVariantSrc = $this->preprocessSourceUri(GeneralUtility::rawUrlEncodeFP($srcsetVariantSrc));
$imageSources[$srcsetVariant[0]] = [
'src' => $srcsetVariantSrc,
'width' => $srcsetVariant[0],
'height' => $srcsetVariant[1],
];
$srcsetVariants[$srcsetVariant[0]] = $srcsetVariantSrc . ' ' . $srcsetVariant[0] . 'w';
}
$tag->addAttribute('srcset', implode(',', $srcsetVariants));
if ('BE' === TYPO3_MODE) {
FrontendSimulationUtility::resetFrontendEnvironment();
}
return $imageSources;
}
/**
* generates a copy of a give image with a specific width
*
* #param string $src path of the image to convert
* #param integer $width width to convert the image to
* #param integer $height height to convert the image to
* #param string $format format of the resulting copy
* #param string $quality quality of the resulting copy
* #param string $treatIdAsReference given src argument is a sys_file_reference record
* #param string $crop image crop string
* #param array $params additional params for the image rendering
* #return string
*/
public function getImgResource($src, $width, $height, $format, $quality, $treatIdAsReference, $crop, $params = null)
{
$setup = [
'width' => $width,
'height' => $height,
'treatIdAsReference' => $treatIdAsReference,
'crop' => $crop,
];
if (false === empty($format)) {
$setup['ext'] = $format;
}
if (0 < intval($quality)) {
$quality = MathUtility::forceIntegerInRange($quality, 10, 100, 75);
$setup['params'] .= ' -quality ' . $quality;
}
if ('BE' === TYPO3_MODE && '../' === substr($src, 0, 3)) {
$src = substr($src, 3);
}
return $this->contentObject->getImgResource($src, $setup);
}
/**
* returns an array of srcsets based on the mixed ViewHelper
* input (list, csv, array, iterator)
*
* #return array
*/
public function getSourceSetWidths()
{
$srcsets = $this->arguments['srcset'];
if (true === $srcsets instanceof \Traversable) {
$srcsets = iterator_to_array($srcsets);
} elseif (true === is_string($srcsets)) {
$srcsets = GeneralUtility::trimExplode(',', $srcsets, true);
} else {
$srcsets = (array) $srcsets;
}
return $srcsets;
}
private function getDimensions($width, $height)
{
$widthSplit = [];
$heightSplit = [];
if (false === empty($width)) {
preg_match("/(\\d+)([a-zA-Z]+)/", $width, $widthSplit);
}
if (false === empty($height)) {
preg_match("/(\\d+)([a-zA-Z]+)/", $height, $heightSplit);
}
$dimensions = [
'width'=>(int)$widthSplit[1],
'height'=>(int)$heightSplit[1],
'postWidth'=>$widthSplit[2],
'postHeight'=>$heightSplit[2],
'ratio'=> 0,
];
if (0 < $dimensions['height']) {
$dimensions['ratio'] = $dimensions['width']/$dimensions['height'];
}
return $dimensions;
}
}
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?
iv'e got a problem to receive a complete array (with all the data of the embedded childs collections and objects) of my document. My document looks exactly like this one:
use Doctrine\Common\Collections\ArrayCollection;
/** #Document(collection="user") */
class User {
/** #Id */
protected $id;
/** #String */
protected $firstname;
/** #String */
protected $lastname;
/** #EmbedMany(targetDocument="Email") */
protected $email;
/** #EmbedMany(targetDocument="Address") */
protected $address;
/** #EmbedMany(targetDocument="Subscription") */
protected $subscription;
/**
* Construct the user
*
* #param array $properties
* #throws User_Exception
*/
public function __construct(array $properties = array()) {
$this->email = new ArrayCollection();
$this->address = new ArrayCollection();
$this->subscription = new ArrayCollection();
foreach($properties as $name => $value){
$this->{$name} = $value;
}
}
...
I need a complete array of an embedded collection to output the whole data and render it by json. My query looks like this:
$query = $this->_dbContainer->getDocumentManager()->createQueryBuilder('User')->field('deletedAt')->exists(false);
$result = $query->field('id')->equals($id)->getQuery()->getSingleResult();
For example, if i call the toArray() function like this:
$array = $result->getSubscription()->toArray();
print_r($array);
Then the output ist just an array on top level:
[0] => Object Subscription...
[1] => Object Subscription...
...
How can i easily get an array like this?
[0] => array('subscriptionLabel' => 'value1', 'field' => 'value1', ...)
[1] => array('subscriptionLabel' => 'value2', 'field' => 'value2', ...)
...
Are there any best practises or maybe some missing helper scripts to prevent something ugly like this code (how to handle child -> child -> child szenarios? ugly -> ugly ugly -> ugly ugly ugly -> ...):
$example = array();
foreach($result->getSubscription() as $key => $subscription) {
$example[$key]['subscriptionLabel'] = $subscription->getSubscriptionLabel();
$example[$key]['field'] = $subscription->getField();
...
}
Thanks a lot,
Stephan
Damn simple answer! Just use ->hydrate(false) and it's done.
For find queries the results by
default are hydrated and you get
document objects back instead of
arrays. You can disable this and get
the raw results directly back from
mongo by using the hydrate(false)
method:
<?php
$users = $dm->createQueryBuilder('User')
->hydrate(false)
->getQuery()
->execute();
print_r($users);
I ran into this same need recently and solved it by creating a base class for all my entities with a toArray() function and JsonSerializable. It converts all nested references as well.
/**
* #ODM\MappedSuperclass
*/
abstract class BaseDocument implements \JsonSerializable
{
public function jsonSerialize() {
return $this->toArray();
}
public function toArray() {
$getter_names = get_class_methods(get_class($this));
$gettable_attributes = array();
foreach ($getter_names as $key => $funcName) {
if(substr($funcName, 0, 3) === 'get') {
$propName = strtolower(substr($funcName, 3, 1));
$propName .= substr($funcName, 4);
$value = $this->$funcName();
if (is_object($value) && get_class($value) == 'Doctrine\ODM\MongoDB\PersistentCollection') {
$values = array();
$collection = $value;
foreach ($collection as $obj) {
$values[] = $obj->toArray();
}
$gettable_attributes[$propName] = $values;
}
else {
$gettable_attributes[$propName] = $value;
}
}
}
return $gettable_attributes;
}
}
Now I can serialize the entity as an array or json string with json_encode($doc). Bam.
Tanks to Rooster242, you can even recursively apply toArray to embedded documents which themself extends BaseDocument by using the php is_subclass_of function :
/**
* #ODM\MappedSuperclass
*/
abstract class BaseDocument implements \JsonSerializable
{
public function jsonSerialize() {
return $this->toArray();
}
public function toArray() {
$getter_names = get_class_methods(get_class($this));
$gettable_attributes = array();
foreach ($getter_names as $key => $funcName) {
if(substr($funcName, 0, 3) === 'get') {
$propName = strtolower(substr($funcName, 3, 1));
$propName .= substr($funcName, 4);
$value = $this->$funcName();
if (is_object($value) && is_subclass_of($value,"BaseDocument")) {
$gettable_attributes[$propName] = $value->toArray();
} elseif (is_object($value) && get_class($value) == 'Doctrine\ODM\MongoDB\PersistentCollection') {
$values = array();
$collection = $value;
foreach ($collection as $obj) {
if (is_subclass_of($obj,"BaseDocument")) {
$values[] = $obj->toArray();
} else {
$values[] = $obj;
}
}
$gettable_attributes[$propName] = $values;
}
else {
$gettable_attributes[$propName] = $value;
}
}
}
return $gettable_attributes;
}
}
Just made this a bit more generic, works perfect. Just dont forget to extend it with your documents and embeds.
<?php
namespace App\Documents;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\ODM\MongoDB\PersistentCollection;
/**
* #ODM\MappedSuperclass
*/
abstract class BaseDocument implements \JsonSerializable
{
/**
* #return array
*/
public function jsonSerialize()
{
return $this->toArray();
}
/**
* #return array
*/
public function toArray()
{
$getterNames = get_class_methods(get_class($this));
$gettableAttributes = [];
foreach ($getterNames as $funcName) {
if (substr($funcName, 0, 3) !== 'get') {
continue;
}
$propName = strtolower(substr($funcName, 3, 1));
$propName .= substr($funcName, 4);
$value = $this->$funcName();
$gettableAttributes[$propName] = $value;
if (is_object($value)) {
if ($value instanceof PersistentCollection) {
$values = [];
$collection = $value;
foreach ($collection as $obj) {
/** #var BaseDocument $obj */
if ($obj instanceof \JsonSerializable) {
$values[] = $obj->toArray();
} else {
$values[] = $obj;
}
}
$gettableAttributes[$propName] = $values;
} elseif ($value instanceof \JsonSerializable) {
/** #var BaseDocument $value */
$gettableAttributes[$propName] = $value->toArray();
}
}
}
return $gettableAttributes;
}
}