With sys_language_mode = strict, how to access relations in main language - typo3

For an extbase extension in a 3 language site, records are only created in Language 0.
To access these records with sys_language_mode = strict, each repository has an extended findAll() method:
class ApprenticeshipTimeframeRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
/**
* #return array An array of objects, empty if no objects found
* #api
*/
public function findAll() {
$query = $this->createQuery();
$query->getQuerySettings()->setRespectSysLanguage(FALSE);
$query->getQuerySettings()->setSysLanguageUid(0);
$result = $query->execute();
return $result;
}
}
This works - but not for ObjectStorage (?) Properties
From the model:
/**
* Initializes all ObjectStorage properties
*
* #return void
*/
protected function initStorageObjects() {
$this->apprenticeshipFree = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->apprenticeshipOccupied = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->apprenticeshipUnavailable = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->internshipFree = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->internshipOccupied = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->internshipUnavailable = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
$this->contactPerson = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
All of these are not output in translated versions of the page.
How can I force these to access L=0?
PS: maybe related with https://forge.typo3.org/issues/47192?

Related

How to Get Value from Index controller to Collection in Magento 2

I'm trying to get the value from Index controller.
Controller\Adminhtml\Orders\Index.php :
public function execute()
{
$storeid = $this->getRequest()->getParam('storeid');
$this->settings->setStoreid($storeid);
}
Model\Settings.php
public function setStoreid($storeid)
{
$this->storeid = $storeid;
}
public function getStoreid()
{
return $this->storeid;
}
Model\ResourceModel\Order\Grid\Collection.php :
public function _renderFiltersBefore{
$storeid = $this->getStoreId();
// var_dump($storeid)
// $storeid = 5
$this->getSelect()->where('store_id = ?', $storeid);
}
I want to pass the storeid to the query Collection. I can able to set the storeid from Index class and can able to get the storeid in Collection class. But it doesnt passing to the collection.
If I set the value directly to storeid, ie. $storeid = 5, then collection works fine. Please advice.
Maybe try to use registry
/**
* #var \Magento\Framework\Registry
*/
protected $_registry;
/**
* ...
* ...
* #param \Magento\Framework\Registry $registry,
*/
public function __construct(
...,
...,
\Magento\Framework\Registry $registry,
...
) {
$this->_registry = $registry;
...
...
}
/**
* Setting custom variable in registry to be used
*
*/
public function setCustomVariable()
{
$this->registry->register('custom_var', 'Added Value');
}
/**
* Retrieving custom variable from registry
* #return string
*/
public function getCustomVariable()
{
return $this->registry->registry('custom_var');
}

How to get translated FAL image in extbase (not in Fluid) in TYPO3?

I am trying to get translated FAL image in extbase but it gives me default language FAL image.
I am using TYPO3 7.6.16. Its a multi-language website.
I have created 2 website languages 1) English, 2) Spanish and the default one is Dutch.
Currently I am fetching data from repository and it gives me model with the same FAL image in both translated version and in original version of the record.
How Can I get translated FAL image using extbase (not in Fluid), because I want to return it to JSON response?
Here is the code:
Controller:
$posts = $this->postRepository->findByLanguage($langId);
foreach($posts as $post) {
$output[] = [
'uid' => $post->getUid(),
'title' => $post->getTitle(),
'image' => $post->getImage()->getOriginalResource()->getOriginalFile()->getPublicUrl()
];
}
header('Content-Type: application/json');
echo json_encode($output);
exit();
Here I am getting default language FAL image instead of localised on line $post->getImage()->getOriginalResource()->getOriginalFile()->getPublicUrl()
Repository:
/**
* #return array|\TYPO3\CMS\Extbase\Persistence\QueryResultInterface
*/
public function findByLanguage($langId, $postId = 0)
{
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
$query->getQuerySettings()->setRespectSysLanguage(TRUE);
$query->getQuerySettings()->setLanguageUid($langId);
if ($postId) {
$query->matching(
$query->equals('uid' , $postId)
);
return $query->execute()->getFirst();
}
return $query->execute();
}
Model:
/**
* title
*
* #var string
*/
protected $title;
/**
* image
*
* #var \TYPO3\CMS\Extbase\Domain\Model\FileReference
*/
protected $image = null;
/**
* #return bool $title
*/
public function getTitle() {
return $this->title;
}
/**
* #param string $title
* #return void
*/
public function setTitle($title) {
$this->title = $title;
}
/**
* #return \TYPO3\CMS\Extbase\Domain\Model\FileReference $image
*/
public function getImage() {
return $this->image;
}
/**
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $image
* #return void
*/
public function setImage(\TYPO3\CMS\Extbase\Domain\Model\FileReference $image) {
$this->image = $image;
}
There was a bug where the FAL records (sys_file_reference) of translated (copy translate) contents did not get the lanuguage id of the translation.
I made a bugfix for that: https://github.com/BenjaminBeck/bdm_bugfix_translatecopy - maybe thats your issue?

Symfony2: optimize collection of forms

In a controller of a Symfony2 application, I use collection of elements. The more elements there are, the more time it takes. It sounds logical but it seems that there are repeated traitments:
I create a form from MyCollectionType
in the buildForm method, I add the ElementType that has its own buildForm method.
Then when the form is built by Symfony2 with the list of elements I pass, the buildForm method of the ElementType is called one time for each element
=> is this not possible that the first ELementType is built, then other are cloned?
I don't see why there would be any different there between these subforms, the only difference will appear setting the data and not building the form.
Then I notice the same for the buildView method: there are a lot of repeated processing for each element, where only the data (possibly processing of listeners) may vary.
For example, in my application, with a ElementType having 6 fields, and a collection of 700 elements, it takes up to 30s to render the form.
Is it due to the way that forms are handled, or can be be optimized ?
I add the same problem for one of my application, what I did is that I reimplemented a basic form class prototype, the method names are almost the same that the Symfony2 ones and reimplemented in the most simple way, It looks like this:
class SimpleForm
{
/**
* #var ContainerInterface $container Main application DIC
*/
protected $container;
/**
* #var array $options Options of the form
*/
protected $options = array();
/**
* #var array $options Raw datas for the form.
*/
protected $data = array();
/**
* #var array $options Data of the form against user input.
*/
protected $boundData = array();
/**
* #var array $errors List of errors after form valisation
*/
protected $errors = array();
/**
* #var array $options Tells if the datas were bound to the form.
*/
protected $isBound = false;
/**
* #var array $options Tells if the form validation is ok
*/
protected $isValid = false;
/**
* Main constructor.
*
* #param ContainerInterface $container The main DIC
* #param array $options Options of the form
*/
public function __construct(ContainerInterface $container, $options = array())
{
$this->container = $container;
$this->options = $options;
$this->buildForm();
}
/**
* Add widgets to the form.
*/
public function buildForm()
{
$this->widgets['keywordType'] = self::$keywordTypes;
}
/**
* #return array
*/
public function getOptions()
{
return $this->options;
}
/**
* #param array $options
*/
public function setOptions($options)
{
$this->options = $options;
}
/**
* #return string
*/
public function getEnctype()
{
return isset($this->options['enctype']) ? $this->options['enctype'] : '';
}
/**
* If the form is bound it return the bound datas, it returns the raws datas otherwise.
*
* #return array
*/
public function getData()
{
return $this->isBound ? $this->boundData : $this->data;
}
/**
* #throws \LogicException
*
* #return array
*/
public function getErrors()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before the errors can be retrieved');
}
return $this->errors;
}
/**
* #throws \LogicException
*
* #return array
*/
public function hasErrors()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before the errors can be checked');
}
return !empty($this->errors);
}
/**
* #throws \LogicException
*
* #return array
*/
public function getBoundData()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before getting the form final datas');
}
return $this->boundData;
}
/**
* #param array $data
*
* #return SimpleForm
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Bind the submitted values to the form.
*
* #param array $values The values to bind
*
* #return SimpleForm
*/
public function bind($values)
{
$values = $this->clean($values);
$this->boundData = Tools::arrayDeepMerge($this->data, $values);
$this->isBound = true;
$this->validate();
return $this;
}
/**
* Clean raw form values before the validation.
*
* #param array $values The raw values submitted by the user.
*
* #return array
*/
protected function clean($values)
{
// ...
return $values;
}
/**
* Run the validation against the form.
*
* #return boolean
*/
protected function validate()
{
$this->errors = array();
// ...
$this->isValid = empty($this->errors);
return $this->isValid;
}
/**
* Return the validation state of the form.
*
* #throws \LogicException
*
* #return boolean
*/
public function isValid()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before getting the validation status');
}
return $this->isValid;
}
/**
* Returns the datas that will be necesary for the view.
*
* #return array
*/
public function createView()
{
return array(
'widgets' => $this->widgets,
'options' => $this->options,
'data' => $this->boundData, // Don't forget to escape values against XSS
'enctype' => $this->getEnctype(),
'errors' => $this->errors,
'name' => $this->getName(),
);
}
/**
* #return string The name of the form
*/
public function getName()
{
return 'search';
}
}
In the Twig templates, I just iterate the data to create the form fields, repopulate values and to display the errors. The form is the same but is generated in 100ms instead of 30 seconds... For all the other forms I kept on using the Symfony2 ones.
The answer is simple: You should optimize yours programming skills instead of symfony forms. This is yours next question (of many) about the same issue.
You want to render over 4200 fields with fieldsets and/or divs around each input, so I suspect that 30 second it's the time in which it renders in the browser.

Symfony2 && mongodb simple reference

he guys,
i want to make a simple reference on mongodb documents using symfony2.
i have this two documents and want to store picture references into the requests document. it works for me, if i have only the picture ids in the requests document.
so i need the follow:
can everyone change the document files and make and extends the custum call to get all pictures as object from the requests (picture array)?
my original files:
Document Pictures:
<?php
namespace TestBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* #MongoDB\Document(repositoryClass="TestBundle\Repository\RequestsRepository")
*/
class Requests
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
*/
protected $title;
public function setId($id)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
Document Pictures:
<?php
namespace TestBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* #MongoDB\Document(repositoryClass="TestBundle\Repository\PicturesRepository")
*/
class Pictures
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
*/
protected $filename;
public function setId($id)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
public function setFilename($filename)
{
$this->filename = $filename;
}
public function getTitle()
{
return $this->filename;
}
}
My Basic Calls:
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$request = $dm->getRepository('TestBundle:Requests')->find($requestId);
To my tests:
i added in the requests document the follow:
/**
* #MongoDB\ReferenceMany(targetDocument="Pictures",cascade={"persist"},simple="true")
*/
protected $pictures = array();
public function setPictures($pictures)
{
$this->pictures[] = $pictures;
}
public function getPictures()
{
return $this->pictures;
}
and added pictures like this:
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$photo = $dm->getRepository('TestBundle:Pictures')->find($photoId);
$dm1 = $this->get('doctrine.odm.mongodb.document_manager');
$request = $dm1->getRepository('TestBundle:Requests')->find($requestId);
$request->setPictures($photo);
$dm1->flush();
this works - but i cannot get the pictures by loading the document.
my code to load:
$dm1 = $this->get('doctrine.odm.mongodb.document_manager');
$request = $dm1->getRepository('TestBundle:Requests')->find($requestId);
$pictures = $request->getPictures();
foreach($pictures as $picture)
{
print $picture->getId();
}
THIS WILL NOT WORK. i become the follow error:
Fatal error: Doctrine\ODM\MongoDB\Proxy\ProxyFactory::getProxy():
Failed opening required
'.../app/cache/dev/doctrine/odm/mongodb/Proxies/_CG_TestBundleDocumentPictures.php'
(include_path='.:.../library:/usr/local/zend/share/pear') in
..../test/vendor/doctrine-mongodb-odm/lib/Doctrine/ODM/MongoDB/Proxy/ProxyFactory.php
on line 100
thanks, jan
First off you only need to call doctrine one time in $dm your overloading your resources and thats bad practice. One function, one Doctrine call. Secondly, you need a $dm->persist($request) and then $dm->flush(). Create a OnetoOne between your Documents and then make $pictures an Doctrine Array Collection. Then set a picture like you tried, then make a smiple query and call $request->getPicture()->getId().
Ok i found the error:
In the deps file i have the following lines:
[doctrine-common]
git=http://github.com/doctrine/common.git
version=2.1.4
[doctrine-dbal]
git=http://github.com/doctrine/dbal.git
version=2.1.7
[doctrine]
git=http://github.com/doctrine/doctrine2.git
version=2.1.7
After updating them to:
[doctrine-common]
git=http://github.com/doctrine/common.git
version=2.2.1
[doctrine-dbal]
git=http://github.com/doctrine/dbal.git
version=2.2.1
[doctrine]
git=http://github.com/doctrine/doctrine2.git
version=2.2.1
And doing php bin/vendors update the references will work again

Updating single database cell in Zend Framework Model

Simple one hopefully, is there a specific way i should be updating a single database value using a model in Zend Framework.
I currently do this:
class Model_MyModel extends Zend_Db_Table_Abstract
{
$_name = 'table';
public function updateSetting($id,$status)
{
$data = array(
'status' => $status
);
$this->update($data, 'id = '.$id);
}
}
$update = new Model_MyModel();
$update->updateSetting(10,1);
Obviously i could pass in another argument as the column to update. I just wondered if there was a more "magic" way i should be doing this?
You could write a simple property overloader for this:
class Model_MyModel extends Zend_Db_Table_Abstract
{
protected $_name = 'table';
/**
* Should be a Zend_Db_Table_Row instance
*
* #var Zend_Db_Table_Row
*/
protected $_currentRow = null;
/**
* Property overloader
*
* For more information on this see
* http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
*
* #param string $key
* #param string $value
* #return void
*/
public function __set($key, $value)
{
$row = $this->getCurrentRow();
if (null !== $row)
{
$row->$key = $value;
}
else
{
throw new Exception('Cannot update a column on a non existent row!');
}
}
/**
* Save current row
*
* #return Model_MyModel
*/
public function saveCurrentRow()
{
$row = $this->getCurrentRow();
if (null !== $row)
{
$row->save();
}
else
{
throw new Exception('Cannot save a non existent row!');
}
}
/**
* Set current row
*
* #param Zend_Db_Table_Row $row
* #return Model_MyModel
*/
public function setCurrentRow(Zend_Db_Table_Row $row)
{
$this->_currentRow = $row;
return $this;
}
/**
* Get current row
*
* #return Zend_Db_Table_Row
*/
public function getCurrentRow()
{
return $this->_currentRow;
}
}
You could then do stuff like this:
$model = new Model_MyModel();
$model->status = 'foo';
$model->somecolumn = 'bar'
$model->saveCurrentRow();
Although this approach would require the least editing in your code, an even better approach would be seperating your models from your database tables and use a Data Mapper Pattern as described in the Quickstart.