How to use Zend_File_Transfer? - zend-framework

I have been using normal file upload element to upload files and validate them. But recently, I found out that implementing a Zend_file_tranfer gives much control over the file.
I am searched Everywhere in the internet searching for a simple example to get started with it, but none of them show how they are linked to the element. I dont know where to create the object of Zend_File_Transfer, and how to add it to the element? I basically dont know, how to use it.
Can anyone give me a beginners example of using zend_File_tranfers, in both zend_form and Zend_Controller_Action

In form:
class Application_Form_YourFormName extends Zend_Form
{
public function __construct()
{
parent::__construct($options);
$this->setAction('/index/upload')->setMethod('post');
$this->setAttrib('enctype', 'multipart/form-data');
$upload_file = new Zend_Form_Element_File('new_file');
$new_file->setLabel('File to Upload')->setDestination('./tmp');
$new_file->addValidator('Count', false, 1);
$new_file->addValidator('Size', false, 67108864);
$new_file->addValidator('Extension', false, Array('png', 'jpg'));
$submit = new Zend_Form_Element_Submit('submit');
$submit->setLabel('Upload');
$this->addElements(array($upload_file, $submit));
}
}
In controller:
class Application_Controller_IndexController extends Zend_Controller_Action
{
public function uploadAction()
{
$this->uform = new Application_Form_YourFormName();
$this->uform->new_file->receive();
$file_location = $this->uform->new_file->getFileName();
// .. do the rest...
}
}

When you create your form do something like this in your form:
$image = $this->getElement('image');
//$image = new Zend_Form_Element_File();
$image->setDestination(APPLICATION_PATH. "/../data/images"); //!!!!
$extension = $image->getFileName();
if (!empty($extension))
{
$extension = #explode(".", $extension);
$extension = $extension[count($extension)-1];
$image->addFilter('Rename', sprintf('logo-%s.'.$extension, uniqid(md5(time()), true)));
}
$image
->addValidator('IsImage', false, $estensioni)//doesn't work on WAMPP/XAMPP/LAMPP
->addValidator('Size',array('min' => '10kB', 'max' => '1MB', 'bytestring' => true))//limit to 200k
->addValidator('Extension', false, $estensioni)// only allow images to be uploaded
->addValidator('ImageSize', false, array(
'minwidth' => $img_width_min,
'minheight' => $img_height_min,
'maxwidth' => $img_width_max,
'maxheight' => $img_height_max
)
)
->addValidator('Count', false, 1);// ensure that only 1 file is uploaded
// set the enctype attribute for the form so it can upload files
$this->setAttrib('enctype', 'multipart/form-data');
Then when you submit your form in your controller:
if ($this->_request->isPost() && $form->isValid($_POST)) {
$data = $form->getValues();//also transfers the file
....

Here are some links that can help you.
Zend Documentation
Same Question on SO
Step By Step Toturial
Another Useful Link

Related

Yii2 remember sort option after submit the searchForm

I use an ActiveForm in Yii2 for my SearchModel. After click on search button the form fields remember previous values but SorterDropdown is refreshed.
<?php echo SorterDropdown::widget(['sort' => $dataProvider->sort,
'label' => $model->sortedBy($dataProvider->sort->attributes),])
?>
SorterDropdown is just a wrapper of ButtonDropdown.
How can I forse the SorterDropdown to remember sort order (and show it) after the form submition?
class SorterDropdown extends LinkSorter
{
public $label;
protected function renderSortLinks()
{
$attributes = empty($this->attributes) ? array_keys($this->sort->attributes) : $this->attributes;
$links = [];
foreach ($attributes as $name) {
$links[] = Html::tag('li', $this->sort->link($name, ['tabindex' => '-1']));
}
if (empty($this->label))
$this->label = 'Sort';
return \yii\bootstrap\ButtonDropdown::widget([
'encodeLabel' => false,
'label' => $this->label,
'dropdown' => [
'items' => $links,
],
]);
}
You should add some class to li element, which indicate active state of it and special style in CSS file.

SilverStripe - Multilingual Custom Form Template

I am building a page with two languages (English and German). For this I am using the translatable module offered on the SilverStripe page (http://addons.silverstripe.org/add-ons/silverstripe/translatable). On regular pages it works just like a charm.
The contact form gets created in a controller. By $form->setTemplate I load a custom template for the form, which is located in the template's include subdirectory. In the class file I defined the different TextFields (model part), which I want to use in the form template.
Here is the controller:
class MietenPage extends Page {
private static $db = array (
//Form
'ChoosPakage' => 'Varchar',
'FormEventHeadline' => 'Varchar',
'FormNoteHeadline' => 'Varchar',
'FormContactHeadline' => 'Varchar',
'FormAdditionalHeadline' => 'Varchar',
'FormCheckOverlay' => 'Varchar',
'FormCheckCaseDesign' => 'Varchar',
'FormCheckAGB' => 'Varchar',
'FormSubmit' => 'Varchar',
'AGBAlert' => 'Varchar'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
//...
return $fields;
}
}
class MietenPage_Controller extends Page_Controller {
private static $allowed_actions = array('ContactForm');
public function ContactForm() {
$fields = new FieldList(
//...
);
$actions = new FieldList(
new FormAction('submit', 'Anfrage Senden!')
);
$form = new Form($this, 'ContactForm', $fields, $actions);
$form->setTemplate('ContactFormTemplate');
return $form;
}
public function submit($data, $ContactForm) {
$email = new Email();
//...
}
}
In my template I am calling the form using $ContactForm. This works totally fine, including all functionalities.
My Problem is, that I can not access the variables (like headline or submit button text), which hold the text in my custom template - just emptyness is returned. I think it has to do something with scope, but I can not solve this problem.
From your example I can't see where your variables live, and how you planned to use them, but to create a multlingual form, you'd best use the _t() functionality: https://docs.silverstripe.org/en/3.1/developer_guides/i18n/#translating-text
You'd use that for any 'hardcoded' text, in php as well as in your templates.

silverstripe dataobject searchable

I´m trying to have certain DataObjects (News) displayed in the default SearchResult Page. So the result should display normal Pages and News.
Is there an easy way to accomplish that in Silverstripe 3?
Or is it recommended to code it completely custom - I mean a custom controller/action which handles the search request and creates a result list, which I display then in a custom template?
I found this, but obviously search is disabled right now:
https://github.com/arambalakjian/DataObjects-as-Pages
Thx and regards,
Florian
I usually but together a custom search function after enabling FulltextSearchable. So in _config.php I would have
FulltextSearchable::enable();
Object::add_extension('NewsStory', "FulltextSearchable('Name,Content')");
replacing Name and Content with whatever DBField you want to be searchable. And each searchable DataObject have this in their class to enable search indexes (pretty sure this needs to be added and run dev/build before enabling the extension, and only works on MySQL DB).
static $create_table_options = array(
'MySQLDatabase' => 'ENGINE=MyISAM'
);
then in my PageController I have my custom searchForm and results functions.
Here is the search function that returns the search form, called with $search in the template:
public function search()
{
if($this->request && $this->request->requestVar('Search')) {
$searchText = $this->request->requestVar('Search');
}else{
$searchText = 'Search';
}
$f = new TextField('Search', false, $searchText);
$fields = new FieldList(
$f
);
$actions = new FieldList(
new FormAction('results', 'Go')
);
$form = new Form(
$this,
'search',
$fields,
$actions
);
//$form->disableSecurityToken();
$form->setFormMethod('GET');
$form->setTemplate('SearchForm');
return $form;
}
and here the custom results function to handle the queries...
function results($data, $form, $request)
{
$keyword = trim($request->requestVar('Search'));
$keyword = Convert::raw2sql($keyword);
$keywordHTML = htmlentities($keyword, ENT_NOQUOTES, 'UTF-8');
$pages = new ArrayList();
$news = new ArrayList();
$mode = ' IN BOOLEAN MODE';
//$mode = ' WITH QUERY EXPANSION';
//$mode = '';
$siteTreeClasses = array('Page');
$siteTreeMatch = "MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keyword'$mode)
+ MATCH( Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords ) AGAINST ('$keywordHTML'$mode)";
$newsItemMatch = "MATCH( Name, Content ) AGAINST ('$keyword'$mode)
+ MATCH( Name, Content ) AGAINST ('$keywordHTML'$mode)";
//Standard pages
foreach ( $siteTreeClasses as $c )
{
$query = DataList::create($c)
->where($siteTreeMatch);
$query = $query->dataQuery()->query();
$query->addSelect(array('Relevance' => $siteTreeMatch));
$records = DB::query($query->sql());
$objects = array();
foreach( $records as $record )
{
if ( in_array($record['ClassName'], $siteTreeClasses) )
$objects[] = new $record['ClassName']($record);
}
$pages->merge($objects);
}
//news
$query = DataList::create('NewsStory')->where($newsItemMatch);
$query = $query->dataQuery()->query();
$query->addSelect(array('Relevance' => $newsItemMatch));
$records = DB::query($query->sql());
$objects = array();
foreach( $records as $record ) $objects[] = new $record['ClassName']($record);
$news->merge($objects);
//sorting results
$pages->sort(array(
'Relevance' => 'DESC',
'Title' => 'ASC'
));
$news->sort(array(
'Relevance' => 'DESC',
'Date' => 'DESC'
));
//output
$data = array(
'Pages' => $pages,
'News' => $news,
'Query' => $keyword
);
return $this->customise($data)->renderWith(array('Search','Page'));
}
I add all the Page classes I want to be searched and that extend SiteTree in the $siteTreeClasses array, and the News parts can be pretty much copied for any other DataObjectI need searchable.
I am not saying this is the best solution and this can definitely be improved on, but it works for me and this might be a good stating point.
I have adapted #colymba's solution into a silverstripe module: https://github.com/burnbright/silverstripe-pagesearch
It allows setting the pagetype in the url.
You'll need to substantially overwrite SearchForm->getResults().
It uses Database->searchEngine(), but those are tailored towards SiteTree and Page classes.
The "proper" solution is to feed the data into a search engine like Solr or Sphinx.
We have the SS3-compatible "fulltextsearch" module for this purpose:
https://github.com/silverstripe-labs/silverstripe-fulltextsearch
It's going to take some upfront setup, and is only feasible if you can either host Solr yourself, or are prepared to pay for a SaaS provider. Once you've got it running though, the possibilities are endless, its a great tool!

Changing the height of ckeditor from a zend form

I am trying to set the height of a ckeditor I am using. Here is what I currently have:
$this->addElement('textarea', 'text_field', array(
'filters' => array('StringTrim'),
'validators' => array(
array('StringLength', true, array(0, 3000)),
),
'decorators' => array('ViewHelper'),
'required' => false,
'attribs' => array('class' => 'ckeditor'),
'label' => 'Please enter text below',
'value' => isset($this->_text_data[0]['text']) ? $this->_text_data[0]['text'] : ''
));
This comes from my form, this is then called in my .phtml file by the following:
<?=$this->element->getElement('text_field')?>
I have looked everywhere and tried adding:
'height' => '100px',
and:
'config' => array(
'toolbar' => 'Full',
'width' => '550px',
'height' => '100px',
),
But neither of these have worked. The main reason I need this is I have a text area (using the ckeditor in order to allow the input information to be formatted in a particular way) which is quite long (the default height I am assuming) but it is only ever a few lines input into the box, hence the reason I want it smaller as it takes up too much space on the page.
Thanks in advance
Iain
I made a form element and a helper using ZendX_JQuery_View_Helper_UiWidget to create a CKEditor with the jQuery adapter. Here's the code of both files :
ZendExt_Form_Element_CKEditor :
class ZendExt_Form_Element_CKEditor extends ZendX_JQuery_Form_Element_UiWidget
{
/**
* Use formCKeditor view helper by default
* #var string
*/
public $helper = 'formCKEditor';
/**
* Default ckeditor options
*
* #var array
*/
public $jQueryParams = array(
'toolbar' => 'Basic'
);
}
And ZendExt_View_Helper_FormCKEditor :
class ZendExt_View_Helper_FormCKEditor extends ZendX_JQuery_View_Helper_UiWidget
{
static $set = false;
public function formCKEditor($name, $value = null, $params = null, $attribs = null)
{
$hTextA = new Zend_View_Helper_FormTextarea();
$hTextA -> setView($this -> view);
$xhtml = $hTextA -> formTextarea($name, $value, $attribs);
$xhtml .= '<script type="text/javascript">$(document).ready(function(){$("#' . $this->_normalizeId($name) . '").ckeditor(' . (!is_null($params) ? 'function(){},' . Zend_Json_Encoder::encode($params) : '') . ')});</script>';
if (self::$set == false) {
$this -> view -> headScript() -> appendFile($this -> view -> baseUrl() . '/js/ckeditor/ckeditor.js');
$this -> view -> headScript() -> appendFile($this -> view -> baseUrl() . '/js/ckeditor/adapters/jquery.js');
self::$set = true;
}
return $xhtml;
}
}
You can use it as any other ZF form element once you copied these 2 files into :
* libraries/ZendExt/Form/Element/ for ZendExt_Form_Element_CKEditor class
* libraries/ZendExt/View/Helper/ for ZendExt_View_Helper_FormCKEditor class
and added the ZendExt namespace in your configuration file (or if you already have a library of yours and want to use it, just put both files in it and change the name of the classes to reflect yours). Then, you'll have tel ZF that ZendExt/View/Helper is a directory to look in for view helpers (in a .ini config file it would look like : resources.view.helperPath.ZendExt_View_Helper = "ZendExt/View/Helper").
Then in your code, just call $ckEditor = new ZendExt_Form_Element_CKEditor(); to create a new CKEditor. You may then add all params you want to the element using $ckEditor -> setJQueryParam($key, $value); as specified in the documentation here : http://framework.zend.com/manual/fr/zendx.jquery.html . For example : $ckEditor -> setJQueryParam('height', '100px');. I understand it's not a jQuery component, but it was the easiest way to be able to make it as everything needed is available there.
To display it, in your view just do <?=$this -> ckEditor?> and you're good.
Make sure you put your ckeditor.js and adapters/jquery.js in your public directory under /js/ckeditor/ or change the path accordingly in the helper.
You'll need to specify the dimensions of the editor when you create it (i.e., in the Javascript part). CKEditor replaces the original form element with its own code, so your changes in the dimensions will be lost.
For instance, if you create it using the jQuery interface, it would be something like the following:
var config = {
width: '550px',
height: '100px'
};
// Initialize the editor.
$('.jquery_ckeditor').ckeditor(config);
Hope that helps...

sfWidgetFormInputText weird behaviour

Well, I have this form:
class CaracteristicaForm extends sfForm {
public function configure() {
$this->setWidgets(array(
'caracteristica' => new sfWidgetFormInputText(array('default'=>'hola mundo'))
));
$this->setValidators(array(
'caracteristica' => new sfValidatorString(
array(
'max_length' => 150,
'required' => true
)
)
));
$this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
}
}
and then I try to...
$form = new CaracteristicaForm();
$this->embedForm('caracteristica', $form);
but the rendered inputText does not have any value at all.
What am I missing?
Ok, to reproduce this you need to embed this form into another form (mine is a Doctrine child form) so maybe is something about some method changing the value?
Well, passing an array defaults did the trick:
$form = new CaracteristicaForm(array('caracteristica' => $caracteristica));
Why not try to
$form->setDefault('caracteristica', $caracteristica);
in action?