Zend_File_Transfer: Rename file after upload - zend-framework

I'm trying to rename the uploaded file with the rename-addFilter. The actual upload already works, but the files are just uploaded and not renamed, so how can I do this?
Here's my Controller-Code, that uploads the file:
//Getting the new filename, works perfectly:
$name = explode('.', $form['pic']);
$ext = $name[1];
$mapper = new Application_Model_CmsMap();
$row = $mapper->fetchRow('childId = "' . $id . '" AND type= "pic"');
$new_filename = $row->name.'.'.$ext;
//All images will and are be stored in /public/images/
//Maybe the picture should be replaced, so it should be overwrited, in case it already exists
$upload->addFilter('Rename', array(
'target' => '/images/'.$new_filename,
'overwrite' => true,
)
);
$upload->receive();

Screw Zend.
Good ol' PHP is easy and works perfectly:
rename('images/'.$form['pic'], 'images/'.$new_filename);

Should work :-)
$transferAdapter = new Zend_File_Transfer_Adapter_Http();
$transferAdapter->receive();
$newFilename = 'MY_NEW_FILE';
$filterFileRename = new Zend_Filter_File_Rename(array(
'target' => 'PATH' + $newFilename,
));
$file = $transferAdapter->getFileName();
// new location and name..
$movedFile = $filterFileRename->filter($file);

Related

How correctly to use the snippet() function?

My first Sphinx app almost works!
I successfully save path,title,content as attributes in index!
But I decided go to SphinxQL PDO from AP:
I found snippets() example thanks to barryhunter again but don't see how use it.
This is my working code, except snippets():
$conn = new PDO('mysql:host=ununtu;port=9306;charset=utf8', '', '');
if(isset($_GET['query']) and strlen($_GET['query']) > 1)
{
$query = $_GET['query'];
$sql= "SELECT * FROM `test1` WHERE MATCH('$query')";
foreach ($conn->query($sql) as $info) {
//snippet. don't works
$docs = array();
foreach () {
$docs[] = "'".mysql_real_escape_string(strip_tags($info['content']))."'";
}
$result = mysql_query("CALL SNIPPETS((".implode(',',$docs)."),'test1','" . mysql_real_escape_string($query) . "')",$conn);
$reply = array();
while ($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
$reply[] = $row['snippet'];
}
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print( $output . "<br><br>");
}
}
I have got such structure from Sphinx index:
Array
(
[0] => Array
(
[id] => 244
[path] => DOC7000/zdorovie1.doc
[title] => zdorovie1.doc
[content] => Stuff content
I little bit confused with array of docs.
Also I don't see advice: "So its should be MUCH more efficient, to compile the documents and call buildExcepts just once.
But even more interesting, is as you sourcing the the text from a sphinx attribute, can use the SNIPPETS() sphinx function (in setSelect()!) in the main query. SO you dont have to receive the full text, just to send back to sphinx. ie sphinx will fetch the text from attribute internally. even more efficient!
"
Tell me please how I should change code for calling snippet() once for docs array, but output path (link), title for every doc.
Well because your data comes from sphinx, you can just use the SNIPPET() function (not CALL SNIPPETS()!)
$query = $conn->quote($_GET['query']);
$sql= "SELECT *,SNIPPET(content,$query) AS `snippet` FROM `test1` WHERE MATCH($query)";
foreach ($conn->query($sql) as $info) {
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print("$output<br>{$info['snippet']}<br><br>");
}
the highlighted text is right there in the main query, dont need to mess around with bundling the data back up to send to sphinx.
Also shows you should be escaping the raw query from user.
(the example you found does that, because the full text comes fom MySQL - not sphinx - so it has no option but to mess around sending data back and forth!)
Just for completeness, if REALLY want to use CALL SNIPPETS() would be something like
<?php
$query =$conn->quote($_GET['query']);
//make query request
$sql= "SELECT * FROM `test1` WHERE MATCH($query)";
$result = $conn->query($sql);
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
//build list of docs to send
$docs = array();
foreach ($rows as $info) {
$docs[] = $conn->quote(strip_tags($info['content']));
}
//make snippet reqest
$sql = "CALL SNIPPETS((".implode(',',$docs)."),'test1',$query)";
//decode reply
$reply = array();
foreach ($conn->query($sql) as $row) {
$reply[] = $row['snippet'];
}
//output results using $rows, and cross referencing with $reply
foreach ($rows as $idx => $info) {
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
$snippet = $reply[$idx];
print("$output<br>$snippet<br><br>");
}
Shows putting the rows into an array, because need to lopp though the data TWICE. Once to 'bundle' up the docs array to send. Then again to acully display rules, when have $rows AND $reply both available.

Showing course image on custom page in Moodle

I have created a custom page on which all available courses are displayed. I have also uploaded the image for the course and now want to show the name of the course along with the image. I am able to get the names of courses from the database but how to get the image.
Try something like this
// Create a course_in_list object to use the get_course_overviewfiles() method.
require_once($CFG->libdir . '/coursecatlib.php');
$course = new course_in_list($courseid);
$outputimage = '';
foreach ($course->get_course_overviewfiles() as $file) {
if ($file->is_valid_image()) {
$imagepath = '/' . $file->get_contextid() .
'/' . $file->get_component() .
'/' . $file->get_filearea() .
$file->get_filepath() .
$file->get_filename();
$imageurl = file_encode_url($CFG->wwwroot . '/pluginfile.php', $imagepath,
false);
$outputimage = html_writer::tag('div',
html_writer::empty_tag('img', array('src' => $imageurl)),
array('class' => 'courseimage'));
// Use the first image found.
break;
}
}
echo $outputimage;
You may get course image directly from 'overviewfiles' files area.
function get_course_image()
{
global $COURSE;
$url = '';
require_once( $CFG->libdir . '/filelib.php' );
$context = context_course::instance( $COURSE->id );
$fs = get_file_storage();
$files = $fs->get_area_files( $context->id, 'course', 'overviewfiles', 0 );
foreach ( $files as $f )
{
if ( $f->is_valid_image() )
{
$url = moodle_url::make_pluginfile_url( $f->get_contextid(), $f->get_component(), $f->get_filearea(), null, $f->get_filepath(), $f->get_filename(), false );
}
}
return $url;
}

Send file to Restful service in codeception

I would like to test restful API test for file uploading.
I try to run:
$I->sendPOST($this->endpoint, $postData, ['file' => 'example.jpg']);
and I would like it to behave the same as user sent example.jpg file in file input with name file but it doesn't seem to work this way. I'm getting:
[PHPUnit_Framework_ExceptionWrapper] An uploaded file must be an array or an instance of UploadedFile.
Is it possible to upload file using REST plugin in codeception? Documentation is very limited and it's hard to say how to do it.
I'm also testing API using Postman plugin to Google Chrome and I can upload file without a problem using this plugin.
I was struggling with the same problem recently and found out that there is another way to solve the issue without using Symfony's UploadedFile class. You only need to pass the array with file data in the same format as if it were the $_FILES array. For example, this code works perfectly well for me:
$I->sendPOST(
'/my-awesome-api',
[
'sample-field' => 'sample-value',
],
[
'myFile' => [
'name' => 'myFile.jpg',
'type' => 'image/jpeg',
'error' => UPLOAD_ERR_OK,
'size' => filesize(codecept_data_dir('myFile.jpg')),
'tmp_name' => codecept_data_dir('myFile.jpg'),
]
]
);
Hope this helps someone and prevents from inspecting the framework's source code (which I was forced to do, as the docs skip such an important detail)
After testing it seems to make it work we need to use UploadedFile object as file.
For example:
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$mime = 'image/jpeg';
$uploadedFile = new \Symfony\Component\HttpFoundation\File\UploadedFile($path . $filename, $filename, $mime,
filesize($path . $filename));
$I->sendPOST($this->endpoint, $postData, ['file' => $uploadedFile]);
['file' => 'example.jpg'] format works too, but the value must be a correct path to existing file.
$path = codecept_data_dir();
$filename = 'example-image.jpg';
// copy original test file to have at the same place after test
copy($path . 'example.jpg', $path . $filename);
$I->sendPOST($this->endpoint, $postData, ['file' => $path . $filename]);
The below worked for myself,
On server:
$uploadedResume= $_FILES['resume_uploader'];
$outPut = [];
if (isset($uploadedResume) && empty($uploadedResume['error'])) {
$uploadDirectory = 'uploads/users/' . $userId . '/documents/';
if (!is_dir($uploadDirectory)) {
#mkdir($uploadDirectory, 0777, true);
}
$ext = explode('.', basename($uploadedResume['name']));
$targetPath = $uploadDirectory . md5(uniqid()) . '.' . end($ext);
if (move_uploaded_file($uploadedResume['tmp_name'], $targetPath)) {
$outPut[] = ['success' => 'success', 'uploaded_path' => $targetPath];
}
}
return json_encode($output);
Sorry for the long description code :P
On Testing side:
//resume.pdf is copied in to tests/_data directory
$I->sendPOST('/student/resume', [], ['resume_uploader' => codecept_data_dir('resume.pdf') ]);
#Yaronius's answer worked for me after I removed the following header from my test:
$I->haveHttpHeader('Content-Type', 'multipart/form-data');

Zend File multiple upload with access to seperate file names

I use Zend Framework 1.12 for some file upload system. And using Zend_File_Transfer_Adapter_Http in a form, for upload of two files.
There are two form elements for those two files.
$file1 = new Zend_Form_Element_File('file1');
// other options like setLabel etc.
$this->addElement($file1, 'file1');
$file2 = new Zend_Form_Element_File('file2');
// other options like setLabel etc.
$this->addElement($file2, 'file2');
and I handle the upload process in my controller like this:
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
$adapter = new Zend_File_Transfer_Adapter_Http();
$adapter->setDestination($dirname);
$files = $adapter->getFileInfo();
foreach ($files as $file => $fileInfo) {
if (!$adapter->receive($file)) {
$messages = $adapter->getMessages();
echo implode("\n", $messages);
} else {
$location = $adapter->getFileName($file, true);
$filename = $adapter->getFileName($file, false);
// taking location and file names to save in database..
}
}
}
With these, I can manage upload of two files. But I don't know how to take location of files which is uploaded with the specific Zend_Form_Element_File. For example, i need to know which file is uploaded to $file1 (element in form) and I will save its location to a table in database, and which file is uploaded to $file2 and save its location to another table.
I do not like to use Zend_File_Transfer_Adapter_Http.
I prefer to use code like this:
in application.ini:
data_tmp = APPLICATION_PATH "/../data/tmp"
in Bootstrap:
$options = $this->getOptions();
define('DATA_TMP', $options['data_tmp']);
in form:
$elementFoo = new Zend_Form_Element_File('foo');
$elementFoo->setLabel('Upload File 1:')->setDestination(DATA_TMP);
$elementBar = new Zend_Form_Element_File('bar');
$elementBar->setLabel('Upload File 2:')->setDestination(DATA_TMP);
in controller:
if ($request->isPost()) {
if ($form->isValid($request->getPost())) {
$values = $form->getValues();
$filenameFoo = $values['foo'];
$filenameBar = $values['bar'];
//at this point you know the name of the individual filename
$filePathFoo = DATA_TMP . DIRECTORY_SEPARATOR . $filenameFoo;
$filePathBar = DATA_TMP . DIRECTORY_SEPARATOR . $filenameBar;
//now you have even the physical path of the files
// taking location and file names to save in database..
}
}
my 2 cent.

addFilter Rename ZendFramework

i need to Rename a file with Zend_File_Transfer() only if new file match with old one in the server using some convention like newfile-1.ext where the -1 is the string that is added but Rename filter is strange, i really dont understand so good.
For example, is necesary some like this:
if(file_exists($file)){
$upload->addFilter('Rename', $file);
}
or Rename does it?
thanks
Here is an example from one of my apps. File is recvieved by an Zend_Form
$upload->receive();
$name = $upload->getFileName();
$newFile = 'mynewfile.xyz'
$filterFileRename = new Zend_Filter_File_Rename(array(
'target' => $this->path . $newFile, // path to file
'overwrite' => true
));
$file = $filterFileRename->filter($name);