Sonata Project: Can't access media that referenced to SonataPage - doctrine

I have a Page entity, that has many-to-one association to Media entity from Sonata MediaBundle
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="Application\Sonata\PageBundle\Entity\Page"
table="page__page"
>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="shortContent" type="text" column="short_content" nullable="true" />
<many-to-one field="media" target-entity="Application\Sonata\MediaBundle\Entity\Media">
<join-column name="media_id" />
</many-to-one>
<lifecycle-callbacks>
<lifecycle-callback type="postPersist" method="postPersist"/>
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
When I'm logged as admin - all is right and I can access media in twig with {{ page.getMedia() }}
But, if I open this page in Incognito window, the media of the page will be
null
Any one have any ideas ?

I found a solution for this case.
If we are not logged in as admin we see a snapshot of some page, and when we add a new field into Page entity, snapshot creator didn't know nothing about this field, so we need to extend Sonata\PageBundle\Model\Transformer model
Page.orm.xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="Application\Sonata\PageBundle\Entity\Page"
table="page__page"
>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="shortContent" type="text" column="short_content" nullable="true" />
<many-to-one field="media" target-entity="Application\Sonata\MediaBundle\Entity\Media">
<join-column name="media_id" />
</many-to-one>
<lifecycle-callbacks>
<lifecycle-callback type="postPersist" method="postPersist"/>
</lifecycle-callbacks>
</entity>
</doctrine-mapping>
Snapshot.orm.xml
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
xsi="http://www.w3.org/2001/XMLSchema-instance"
schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity
name="Application\Sonata\PageBundle\Entity\Snapshot"
table="page__snapshot"
>
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<many-to-one field="media" target-entity="Application\Sonata\MediaBundle\Entity\Media">
<join-column name="media_id" />
</many-to-one>
<gedmo:loggable log-entry-class="Gedmo\Loggable\Entity\LogEntry"/>
</entity>
</doctrine-mapping>
And page to snapshot transformer class
PageTransformer.php
<?php
namespace Application\Sonata\PageBundle\Entity;
use Sonata\PageBundle\Entity\Transformer;
use Sonata\PageBundle\Model\PageInterface;
use Sonata\PageBundle\Model\SnapshotInterface;
class PageTransformer extends Transformer
{
public function create(PageInterface $page)
{
/** #var Snapshot $snapshot */
$snapshot = parent::create($page);
$content = $snapshot->getContent();
$snapshot->setContent($content);
$snapshot->setMedia($page->getMedia());
return $snapshot;
}
public function load(SnapshotInterface $snapshot)
{
$page = parent::load($snapshot);
$page->setMedia($snapshot->getMedia());
return $page;
}
}
Almost forget!!! We need to say Sonata to use our Transformer class
parameters.yml
parameters:
sonata.page.transformer.class: Application\Sonata\PageBundle\Entity\PageTransformer

Related

Company custom fields's value not saving in company admin form(Magento b2b)

I have created some custom fields in company table. After creating the fields in company form, i have used one event to save the custom value in database. So, first time the value is saving in database but it is not saving in UI component form rather it is showing as a blank.
customer_form.xml
<fieldset name="proofofbusiness" sortOrder="100">
<settings>
<collapsible>true</collapsible>
<label> Proof of Business </label>
</settings>
<field name="gst_number" formElement="input">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="source" xsi:type="string">gst_number</item>
</item>
</argument>
<settings>
<label translate="true">GST Number</label>
<dataType>text</dataType>
<dataScope>gst_number</dataScope>
</settings>
</field>
</fieldset>
2)di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Company\Model\Company\DataProvider" type="Arijit\CustomerShop\Model\CustomerShop\DataProvider" />
<type name="Magento\Company\Model\Company\DataProvider">
<plugin name="after_save_company_additional_field"
type="Arijit\CustomerShop\Plugin\AdditionalDataProvider"/>
</type>
</config>
3)db_schema.xml
<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
<table name="company" resource="default" engine="innodb">
<column xsi:type="varchar" name="gst_number" nullable="true"/>
</table>
</schema>
Dataprovider.php(Added custom field)
public function getProofOfBusiness(CompanyInterface $company)
{
return [
'gst_number'=> $company->getGstNumber(),
];
}
I can see that the fieldset name is not matching the function name that returns its data. The fieldset name is "proofofbusiness" so your function in DataProvider.php should be named getProofofbusinessData().

Propel2 Reverse second run has deleted columns

I am new to propel. There doesn't appear to be a version command built in, but composer shows propel2 in my description.
I reverse engineered my scheme and models from the database then took six months off the project, came back, remastered the database directly, deleted the generated-classes, and the generated-reversed-database.
I then ran
propel reverse "mysql:host=localhost;dbname=MyVanLog;user=**;password=**"
When that completed I opened my schema.xml file and visually verified that the fuel price column no longer exists.
<table name="LogEntries" idMethod="native" phpName="Logentries">
<column name="LogEntryId" phpName="Logentryid" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
<column name="UserId" phpName="Userid" type="INTEGER" primaryKey="true" required="true"/>
<column name="RvId" phpName="Rvid" type="INTEGER" primaryKey="true" required="true"/>
<column name="Title" phpName="Title" type="VARCHAR" size="45" required="true"/>
<column name="Description" phpName="Description" type="CLOB"/>
<column name="Longitude" phpName="Longitude" type="DECIMAL" size="10" scale="8"/>
<column name="Latitude" phpName="Latitude" type="DECIMAL" size="10" scale="8"/>
<column name="Temperature" phpName="Temperature" type="DECIMAL" size="3" scale="1"/>
<column name="Private" phpName="Private" type="VARCHAR" size="1" sqlType="bit(1)" required="true"/>
<column name="CreatedOnUTC" phpName="Createdonutc" type="TIMESTAMP" required="true"/>
<column name="ModifiedOnUTC" phpName="Modifiedonutc" type="TIMESTAMP" required="true"/>
<foreign-key foreignTable="Users" name="FK_36">
<reference local="UserId" foreign="UserId"/>
</foreign-key>
<foreign-key foreignTable="Rvs" name="FK_40">
<reference local="RvId" foreign="RvId"/>
<reference local="UserId" foreign="UserId"/>
</foreign-key>
<index name="fkIdx_36">
<index-column name="UserId"/>
</index>
<index name="fkIdx_40">
<index-column name="RvId"/>
<index-column name="UserId"/>
</index>
<vendor type="mysql">
<parameter name="Engine" value="InnoDB"/>
</vendor>
Then I run propel build to generate my models. I open my base/LogEntries file and it has all the methods to manipulate the field that is no longer there. I won't paste the entire file, but here is the get method.
/**
* Get the [fuelpriceinvalid] column value.
*
* #return string
*/
public function getFuelpriceinvalid()
{
return $this->fuelpriceinvalid;
}
Does anyone know what I missed?
I had an extra schema.xml file hanging out in the project directories that was being read instead of the one I generated causing the old fields to generate. This was likely just a mistake on my part, not a propel bug.

Spring Castor Unmarshalling with Mapping

I am trying to unmarshall an XML to Object using Castor OXM Unmarshalling in Spring.
XML:
<LevelA>
<LevelB>
<item name="itemA">value</item>
<item name="itemB">value</item>
<item name="itemC">value</item>
<item name="itemD">value</item>
<item name="itemE">value</item>
</LevelB>
</LevelA>
Object:
Class LevelA {
LevelB objLevelB;
//getter and setter
}
Class LevelB {
List<Items> item = new ArrayList<Items>();
//getter and setter
}
Class Items {
String Name;
String Value;
//getter and setter
}
Castor Mapping:
<mapping>
<class name="LevelA">
<map-to xml="LevelA" />
<field name="objLevelB" type="LevelB">
<bind-xml name="LevelB" />
<class name="LevelB">
<field name="item" type="Items" collection="arraylist">
<bind-xml name="item" node="element" />
<class name="Items">
<field name="Name" type="string">
<bind-xml name="name" node="attribute" />
</field>
<field name="Value" type="string">
<bind-xml node="text" />
</field>
</class>
</field>
</class>
</field>
</class>
</mapping>
I am getting the following error:
org.xml.sax.SAXException: unable to find FieldDescriptor for 'item' in ClassDescriptor of LevelB
I have tried several ways and spent enough time that I need some help from you all now.
Any help would be useful.
Figured out the way myself, here is the mapping that worked for me. I am sharing the answer to help others, in the same situation.
<?xml version="1.0" encoding="UTF-8"?>
<mapping>
<description> Provides Mapping to Convert Document to POJO</description>
<class name="LevelAClass">
<map-to xml="LevelA" />
<field name="objLevelB" type="LevelBClass">
<bind-xml name="LevelB" />
</field>
</class>
<class name="LevelBClass">
<field name="item" type="LevelCClass"
collection="arraylist">
<bind-xml name="item" />
</field>
</class>
<class name="LevelCClass">
<field name="Name">
<bind-xml name="name" node="attribute" />
</field>
<field name="Value">
<bind-xml name="item" node="text" />
</field>
</class>
</mapping>

How to configure Doctrine entities to handle compressed blobs in the database?

I'm using Doctrine 2 as an ORM to the database and i'm having an issue with compressed blobs.
I'm storing text in a compressed blob column in the database. How can i specify this in the entity mapping xml config? I'm currently using type="blob" for this column but this isn't returning a string. I could use type="text" but this returns garbage as it's not uncompressing it.
Can i specify somewhere in my entity config that this text need uncompressing on retrieval and compressing on persisting?
Here's my entity configuration:
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="AccountNote" table="tblAccountNote">
<id name="intAccountNoteId" type="integer">
<generator strategy="AUTO" />
</id>
<field name="intAccountId" type="integer" nullable="false" unique="no" />
<field name="bolHiddenNote" type="boolean" nullable="false" unique="no" />
<field name="binNote" type="blob" nullable="false" unique="no" />
<field name="strHash" type="string" length="32" nullable="true" unique="no" />
<field name="dtmCreated" type="datetime" nullable="false" unique="no" />
<field name="stmTimestamp" type="datetime" nullable="false" unique="no" />
<many-to-one field="objAccount" target-entity="Account" inversed-by="objNotes">
<join-column name="intAccountId" referenced-column-name="intAccountId" />
</many-to-one>
</entity>
</doctrine-mapping>
In the end we decided on handling the compression in the getter and setter and removing it from the schema.

How do I find a list of subclasses for a propel model with concrete inheritance

I'm building a mini-cms for my local charity (yes, I know I could use a floss project, but they want custom coded)
My propel schema currently looks as such:-
<?xml version="1.0" encoding="UTF-8"?>
<database name="sja" defaultIdMethod="native">
<table name="section">
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true" />
<column name="title" type="VARCHAR" required="true" />
<column name="slug" type="VARCHAR" required="true" />
</table>
<table name="page">
<column name="id" type="INTEGER" primaryKey="true" required="true" autoIncrement="true" />
<column name="title" type="VARCHAR" required="true" />
<column name="section_id" type="INTEGER" required="true" />
<foreign-key foreignTable="section">
<reference local="section_id" foreign="id" />
</foreign-key>
</table>
<table name="static_page">
<behavior name="concrete_inheritance">
<parameter name="extends" value="page" />
</behavior>
<column name="content" type="LONGVARCHAR" required="true" />
</table>
<table name="home_page">
<behavior name="concrete_inheritance">
<parameter name="extends" value="page" />
</behavior>
<column name="standfirst_title" type="VARCHAR" />
<column name="standfirst_image" type="VARCHAR" />
<column name="standfirst_content" type="VARCHAR" />
</table>
</database>
I want to be able to get a list that would include "home_page" and "static_page" - without having to create this manually whenever I add a new page type.
Is there an easy way to get a list like this, or do I have to write some magic stuff with Reflection Classes, etc?
After a poke in the right direction from #propel on freenode - I've come up with this for a base concept - haven't tested it yet though
function getSubClasses()
{
$map = $this->getDatabaseMap();
$children = array();
foreach ($map->getRelations() AS $relation)
{
$behaviours = $relation->getRightTable()->getBehaviours();
if (issset($behaviours['concrete_inheritance']['extends']) AND $behaviours['concrete_inheritance']['extends'] == $this->getDatabaseMap()->getClassName())
{
$children[] = $relation->getRightTable()->getClassName();
}
}
return $children;
}

Resources