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;
}
}
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);
I am new to MongoDB.
I am using Jensegger/Laravel-MongoDB Moloquent features to work on Mongo DB.
I am trying to create an index of a collection in this method:-
Schema::collection('events', function ($table) {
$table->index(['location' => '2dsphere']);
});
However, I am getting error:-
Class Jenssegers\Mongodb\Schema' not found
I have added these two as well:-
use Jenssegers\Mongodb\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
I have a controller method which is given below:-
public function fetchMongoTest(Request $request){
$error = FALSE;
$respond = array();
$detail = array();
$err_message = array();
$err_validation = array();
$api_code = 2001;
try
{
if ($request->isMethod('post'))
{
$latitude = (float)$request->latitude;
$longitude = (float)$request->longitude;
$status = 1;
$mongoData = array();
$monTestObj = new Mongotest;
Schema::collection('events', function ($table) {
$table->index(['location' => '2dsphere']);
});
$monTestObj->location = ['type' => 'Point', 'coordinates' => [100.0, 0.0]];
$monTestObj->save();
$users = MongoTest::where('loc', 'near', [
'$geometry' => [
'type' => 'Point',
'coordinates' => [
$longitude,
$latitude
]
],
'$maxDistance' => 10,
]);
foreach($users as $u)
{
print_r($u->name);
}
}
else
{
$status = 0;
$message = Config::get('customConfig.api_messages.ENG.post_request_mandatory');
$err_message[] = $message;
}
}
catch(Exception $e)
{
$status = 0;
echo $e->getMessage(); die;
$message=Config::get('customConfig.api_messages.ENG.exception_error');
}
$response['status'] = $status;
$response['message'] = $message;
$response['details'] = $detail;
$response['error'] = $err_message;
$response['error_validation_key'] = $err_validation;
$response['api_version'] = $this->api_version;
$response['api_code'] = $api_code;
$respond['fetch-activity-list-prime'] = $response;
$jsonResult = json_encode($respond);
header('Content-Type: application/json; charset=utf-8');
echo $jsonResult ;
exit();
}
How can I check if a collection exists and if not, create a new collection?
EDIT:
This is my MongoTest model:-
<?php
namespace App\Http\Model;
//use Illuminate\Database\Eloquent\Model;
use Moloquent;
class MongoTest extends Moloquent
{
protected $connection = 'mongodb';
protected $collection = 'test';
//protected $collection = 'rh_country_help_text';
}
You seems to have picked up a partial answer from somewhere. The Schema should be picked up from a "Larvel Migration", which is one recommended way of actually defining indexes in your application.
The process would be to set up like:
Create the Migration
php artisan make:migration create_location_index
Then alter the structure to add the up and down for create and drop of the index:
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLocationIndex extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::connection('mongodb')->table('test', function (Blueprint $collection) {
$collection->index([ "loc" => "2dsphere" ]);
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::connection('mongodb')->table('test', function (Blueprint $collection) {
$collection->dropIndex(['loc_2dsphere']);
});
}
}
Then you can run the migration as detailed within the documentation
If you decide to run the code outside of a migrations process then alternate handles for getting the MongoDB\Collection object can be like:
DB::collection('test')->raw(function($collection) {
return $collection->createIndex([ 'loc' => '2dsphere' ])
}
Whatever you do though this code does not belong in the controller. The code to create an index need only be run once. Typically "once only" on your database deployment, but it does not really hurt to issue the command on every application start up, however it certainly hurts with every request. So just don't put it there.
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.
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;
}
}
I can't get fileprg plugin to work with the files in a collection.
I am trying to upload multiple files using FormCollections, but in $form->getData() there is no key related to my collection or the files .
I tested the form and fileprg with simple file input (in the same form) and it worked uploaded/renamed and it was in the $form->getData().
what am i missing ? is there anything special to be done with the collections to get it to work ?
In the file \Zend\Mvc\Controller\Plugin\FilePostRedirectGet the two functions you want to look at are getNonEmptyUploadData (that is supplying a callback function) and traverseInputs (which is a glorified foreach that checks each input filter then runs it and the value through the above callback).
To allow this plugin to work on collections you will need to extend the class and alter the above functions:
/**
* Traverse the InputFilter and run a callback against each Input and associated value
*
* #param InputFilterInterface $inputFilter
* #param array $values
* #param callable $callback
* #return array|null
*/
protected function traverseInputs(InputFilterInterface $inputFilter, $values, $callback)
{
$returnValues = null;
foreach ($values as $name => $value) {
if (!$inputFilter->has($name)) {
continue;
}
$input = $inputFilter->get($name);
if ($input instanceof InputFilterInterface && is_array($value)) {
if ($input instanceof CollectionInputFilter) {
$retVal = null;
foreach ($value as $k => $val) {
$retVal2 = $this->traverseInputs($input->getInputFilter(), $val, $callback);
if ($retVal2)
$retVal[$k] = $retVal2;
}
} else
$retVal = $this->traverseInputs($input, $value, $callback);
if (null !== $retVal) {
$returnValues[$name] = $retVal;
}
continue;
}
$retVal = $callback($input, $value);
if (null !== $retVal) {
$returnValues[$name] = $retVal;
}
}
return $returnValues;
}
/**
* Traverse the InputFilter and only return the data of FileInputs that have an upload
*
* #param InputFilterInterface $inputFilter
* #param array $data
* #return array
*/
protected function getNonEmptyUploadData(InputFilterInterface $inputFilter, $data)
{
return $this->traverseInputs(
$inputFilter,
$data,
function ($input, $value) {
$messages = $input->getMessages();
if (is_array($value) && $input instanceof FileInput && empty($messages)) {
$rawValue = $value;
if (
(isset($rawValue['error']) && $rawValue['error'] !== UPLOAD_ERR_NO_FILE)
|| (isset($rawValue[0]['error']) && $rawValue[0]['error'] !== UPLOAD_ERR_NO_FILE)
) {
return $value;
}
}
return;
}
);
}
Here is a diff that shows what lines were altered: https://github.com/rafam31/zf2/commit/c481e7404faf93beb4c67a6a4b7490fec15d279b