Does Laravel Input::hasfile() work on input arrays? - file-upload

I'm working on a Laravel project that uses a form with multiple file inputs. If I submit the form with the first input empty and all other inputs with a file, then hasFile returns false. It will only return true if the first input contains a file.
if(Input::hasfile('file'))
{
// do something
}
This is the input array via Input::file('file). The small image input is empty, but the large is not. I'd like it to look at the whole array and if there any files present, then proceed with the "do something".
Array
(
[small] =>
[large] => Symfony\Component\HttpFoundation\File\UploadedFile Object
(
[test:Symfony\Component\HttpFoundation\File\UploadedFile:private] =>
[originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => image_name.jpg
[mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => image/jpeg
[size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 44333
[error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
[pathName:SplFileInfo:private] => /Applications/MAMP/tmp/php/phpHILgX2
[fileName:SplFileInfo:private] => phpHILgX2
)
)
Is this expected behavior? Or, should it be looking at the entire array?

You can check by using the array key for example like below :-
HTML Input type File Element :
<input type="file" name="your_file_name[]" />
Laravel 5 : $request->hasFile('your_file_name.'.$key)
Laravel 4.2 : Input::hasFile('your_file_name.'.$key)

Taken from source:
/**
* Determine if the uploaded data contains a file.
*
* #param string $key
* #return bool
*/
public function hasFile($key)
{
if (is_array($file = $this->file($key))) $file = head($file);
return $file instanceof \SplFileInfo;
}
It seems that it only checks the first one from the array, head returns the first item from the array.

Since I can't comment, seems I'll have to post.
Ronak Shah's answer really should be marked the correct one here, and when I figured out why, it instantly had me saying "Sonnofa--" after 30-40 minutes trying to figure this... "mess" out.
Turns out to use hasFile() on an input array, you need to use dot notation.
So (using my own example) instead of
$request->hasFile("img[29][file]")
it needs to be
$request->hasFile("img.29.file")
That's certainly an eye-opener, given that PHP and dot notation don't really go together. Input arrays really are problem children.

here is a snippet that may help
if(Input::hasFile('myfile')){
$file = Input::file('myfile');
// multiple files submitted
if(is_array($file))
{
foreach($file as $part) {
$filename = $part->getClientOriginalName();
$part->move($destinationPath, $filename);
}
}
else //single file
{
$filename = $file->getClientOriginalName();
$uploadSuccess = Input::file('myfile')->move($destinationPath, $filename);
}
} else {
echo 'Error: no file submitted.';
}
Taken from
http://forumsarchive.laravel.io/viewtopic.php?id=13291

At the time of writing (Laravel 8) the Request class now supports arrays for the hasFile method, as from the source code:
/**
* Determine if the request contains the given file.
*
* #param string $name
* #param string|null $value
* #param string|null $filename
* #return bool
*/
public function hasFile($name, $value = null, $filename = null)
{
if (! $this->isMultipart()) {
return false;
}
return collect($this->data)->reject(function ($file) use ($name, $value, $filename) {
return $file['name'] != $name ||
($value && $file['contents'] != $value) ||
($filename && $file['filename'] != $filename);
})->count() > 0;
}

Related

TYPO3 extension Model conflict with f:form.upload

For an own extension, I want o use the viewhelper f:form.upload
to retrieve the upload parameters I have to define the property for this viewhelper as an array. These work fine to get the name, type, tmp_name, error, and size parameters.
In the Domain Model, I read the parameters and save the uploaded file and store the file name inside the database. That works fine! Here the part of the Domain Modell for the variable iFile:
/**
* iFile
*
* #var array
* #TYPO3\CMS\Extbase\Annotation\ORM\Cascade("remove")
*/
protected $iFile = [];
/**
* Returns the iFile
*
* #return string iFile
*/
public function getIFile()
{
$temp = [];
$temp['image_name'] = $this->iFile;
error_log("Get_iFile: " . var_export($temp, true), 0);
error_log("Get_iFile0: " . var_export($this, true), 0);
return $temp;
}
/**
* Sets the iFile
*
* #param string $iFile
* #return void
*/
public function setIFile($iFile)
{
if($iFile['tmp_name'] != ""){
$docRoot = $_SERVER['DOCUMENT_ROOT'].'\\' ;
if (!is_dir($docRoot)) {
mkdir($docRoot, 07777, true);
}
$date = new \DateTime();
$fName = 'fileadmin\\Radio\\crNews\\' . $date->format('Ymd') . $iFile['name'];
if(copy($iFile['tmp_name'], $docRoot . $fName) == true);
unlink($iFile['tmp_name']);
}
error_log("Set _FILES: " . var_export($iFile, true), 0);
$this->iFile = $fName;
}
But if I try to read it from the database, I don't get back the file name from the database! Only an empty array.
'iFile' =>
array (
),
The problem seems to be, due to the definition of iFile as an array.
How can I solve the problem?
Is there any possibility, to add a new variable to the Model as an array, but not to store it in the database?
So I found a workaround. I only defined iFile as an string to read and save the file name in the database and used the $_FILES post variables to retrieve the name and tmp_name of the $_FILES.
In Typo3, access the $_FILES parameters is not so easy. So I recommend to use phpinstruction error_log("Create _FILES: " . var_export($_FILES, true), 0); to find out the structure of the array.

Why is "deleteBlocks" not working in phpWord?

I´m trying to use blocks in my Word document but I´m having some problems. First of all, when I declare a block in my document, if I don´t use the function "cloneBlock", the result appears like this:
${sec}
example
${/sec}
Maybe I must use that function to appear properly. But my main problem is that "deleteBlock" is not working. If I don´t clone the block, the generated docx is corrupted. But if I clone the block, the function "deleteBlock" doesn´t delete the block and it appear the information that is inside that block in my final docx file.
This is my code:
//Word
// Creating the new document...
$templateProcessor = new \PhpOffice\PhpWord\TemplateProcessor('../example.docx');
//set value
//$templateProcessor->setValue('title', 'Example');
//Triplicate block
$templateProcessor->cloneBlock('firstblock', 3, true, true);
$templateProcessor->setValue('firstname#1', 'John');
$templateProcessor->setValue('lastname#1', 'Doe');
$templateProcessor->setValue('firstname#2', 'John');
$templateProcessor->setValue('lastname#2', 'Doe');
$templateProcessor->setValue('firstname#3', 'John');
$templateProcessor->setValue('lastname#3', 'Doe');
//Delete Block
$templateProcessor->cloneBlock('sec', 1, true, true);
$templateProcessor->deleteBlock('sec');
$templateProcessor->saveAs('example.docx');
Docx template:
${firstblock}
Hello ${firstname} ${lastname}!
${/firstblock}
${sec}
example
${/sec}
UPDATE:
Instead of using the function "deleteBlock", I have use the function "cloneBlock" like this and it deletes the block:
//Delete Block
$templateProcessor->cloneBlock('sec', 0, true, true);
So, I have write to clone the block 0 times, so it disappears
But I have another problem. I don´t know why, but this only works sometimes
I'm not sure why user #d1845412 deleted their previous answer, but it actually solved my issue. I overwrote the deleteBlock method with the following code and it seems to work. I prefer this small change over larger changes to the replaceBlock method.
/**
* Override this method since deleteBlock doesn't seem to work.
* #param string $blockname
*/
public function deleteBlock($blockname)
{
$this->cloneBlock($blockname, 0, true, true);
}
Try this. I slightly changed the regexp in replaceBlock, I also added a function that removes unused patterns, it may come in handy) I'll warn you right away - not really testing so use it carefully
class PatchedTemplateProcessor extends TemplateProcessor
{
/**
* Remove ${*} and ${/*} from temporary document
*/
public function removeSearchPatterns()
{
preg_match_all(
'/(\$\{[^\}]*\})/',
$this->tempDocumentMainPart,
$matches,
PREG_SET_ORDER
);
foreach ($matches as $match){
$this->tempDocumentMainPart = str_replace(
$match,
'',
$this->tempDocumentMainPart
);
}
}
/**
* #param string $blockname
* #param string $replacement
*/
public function replaceBlock($blockname, $replacement)
{
$matches = array();
preg_match(
'/(<w:t.*>\${' . $blockname . '}<\/w:.*?t>)(.*)(<w:t.*\${\/' . $blockname . '}<\/w:.*?t>)/is',
$this->tempDocumentMainPart,
$matches
);
if (isset($matches[3])) {
$this->tempDocumentMainPart = str_replace(
$matches[2] . $matches[3],
$replacement,
$this->tempDocumentMainPart
);
}
}
/**
* Delete a block of text.
*
* #param string $blockname
*/
public function deleteBlock($blockname)
{
$this->replaceBlock($blockname, '');
}
}

Object of class PDOStatement could not convert to string

I changed my mysqli connection to PDO statment so i have to much error on my page this is the my code pls help us
.
.
.
if ($fn && $ln && $e && $p) { // If everything's OK...
// Make sure the email address is available:
//$q = "SELECT user_id FROM users WHERE email='$e'";
$q = $dbc->query("SELECT user_id FROM users WHERE email='$e'");
$q->execute(array($e));
$r = $q->fetchAll(PDO::FETCH_ASSOC);
//$r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
if (mysqli_num_rows($r) == 0) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
Here is your code converted to PDO.
// Make sure the email address is available:
$q = $dbc->query("SELECT user_id FROM users WHERE email=?");
$q->execute(array($e));
$r = $q->fetchColumn();
if (!$r) { // Available.
// Create the activation code:
$a = md5(uniqid(rand(), true));
Three things has been corrected
You have to always use a placeholder tp represent a variable in the query.
To get a single value from the result, fetchColumn have to be used instead of fetchAll
No need for the manual reporting, as PDO can report its errors automatically, if confugired properly, as described in this tutorial I wrote

Using boolean fields with Magento ORM

I am working on a backend edit page for my custom entity. I have almost everything working, including saving a bunch of different text fields. I have a problem, though, when trying to set the value of a boolean field.
I have tried:
$landingPage->setEnabled(1);
$landingPage->setEnabled(TRUE);
$landingPage->setEnabled(0);
$landingPage->setEnabled(FALSE);
None seem to persist a change to my database.
How are you supposed to set a boolean field using magento ORM?
edit
Looking at my database, mysql is storing the field as a tinyint(1), so magento may be seeing this as an int not a bool. Still can't get it to set though.
This topic has bring curiosity to me. Although it has been answered, I'd like to share what I've found though I didn't do intense tracing.
It doesn't matter whether the cache is enabled / disabled, the table schema will be cached.
It will be cached during save process.
Mage_Core_Model_Abstract -> save()
Mage_Core_Model_Resource_Db_Abstract -> save(Mage_Core_Model_Abstract $object)
Mage_Core_Model_Resource_Db_Abstract
public function save(Mage_Core_Model_Abstract $object)
{
...
//any conditional will eventually call for:
$this->_prepareDataForSave($object);
...
}
protected function _prepareDataForSave(Mage_Core_Model_Abstract $object)
{
return $this->_prepareDataForTable($object, $this->getMainTable());
}
Mage_Core_Model_Resource_Abstract
protected function _prepareDataForTable(Varien_Object $object, $table)
{
$data = array();
$fields = $this->_getWriteAdapter()->describeTable($table);
foreach (array_keys($fields) as $field) {
if ($object->hasData($field)) {
$fieldValue = $object->getData($field);
if ($fieldValue instanceof Zend_Db_Expr) {
$data[$field] = $fieldValue;
} else {
if (null !== $fieldValue) {
$fieldValue = $this->_prepareTableValueForSave($fieldValue, $fields[$field]['DATA_TYPE']);
$data[$field] = $this->_getWriteAdapter()->prepareColumnValue($fields[$field], $fieldValue);
} else if (!empty($fields[$field]['NULLABLE'])) {
$data[$field] = null;
}
}
}
}
return $data;
}
See the line: $fields = $this->_getWriteAdapter()->describeTable($table);
Varien_Db_Adapter_Pdo_Mysql
public function describeTable($tableName, $schemaName = null)
{
$cacheKey = $this->_getTableName($tableName, $schemaName);
$ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
if ($ddl === false) {
$ddl = parent::describeTable($tableName, $schemaName);
/**
* Remove bug in some MySQL versions, when int-column without default value is described as:
* having default empty string value
*/
$affected = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint');
foreach ($ddl as $key => $columnData) {
if (($columnData['DEFAULT'] === '') && (array_search($columnData['DATA_TYPE'], $affected) !== FALSE)) {
$ddl[$key]['DEFAULT'] = null;
}
}
$this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
}
return $ddl;
}
As we can see:
$ddl = $this->loadDdlCache($cacheKey, self::DDL_DESCRIBE);
will try to load the schema from cache.
If the value is not exists: if ($ddl === false)
it will create one: $this->saveDdlCache($cacheKey, self::DDL_DESCRIBE, $ddl);
So the problem that occurred in this question will be happened if we ever save the model that is going to be altered (add column, etc).
Because it has ever been $model->save(), the schema will be cached.
Later after he add new column and "do saving", it will load the schema from cache (which is not containing the new column) and resulting as: the data for new column is failed to be saved in database
Delete var/cache/* - your DB schema is cached by Magento even though the new column is already added to the MySQL table.

Is this little Doctrine2 dynamic SQL enough safe of injection?

I kwnow that using an ORM like Doctrine2 for building queries is safe, meaning that parameters are escaped by default.
But i'm guessing that this is not so obvious when using literals and when this literal comes directly from the query string:
$builder = $this->getRepository()->createQueryBuilder('e');
$request = $this->getRequest();
// Loop each allowed filter field and check if exists in $request
foreach($this->getFilterFields() as $filter) :
// Skip falsy values in $request
if(!$value = $request->get($filter)) continue;
// Add OR LIKE %$value% where $value is GET paramter
$like = $builder->expr()->literal("%$value%");
$builder->orWhere($builder->expr()->like("e.$filter", $like));
endforeach;
Should safety be improved in some way?
$queryBuilder->expr returns an ExpressionBuilder object. Inside ExpressionBuilder we find:
public function literal($input, $type = null)
{
return $this->connection->quote($input, $type);
}
So literals do get quoted and should be fine to use.
We also find:
public function like($x, $y)
{
return $this->comparison($x, 'LIKE', $y);
}
public function comparison($x, $operator, $y)
{
return $x . ' ' . $operator . ' ' . $y;
}
$y is fine because it goes through literal first. Do want to be a bit careful about $x. As long as your filterFields are internal then no problem. If they are coming from the user then you need to make sure they are valid.