Issues with DCE on TYPO3 upgrade - typo3

I have Upgraded typo3 from 9.5.5 to 10.4.19 and DCE from 2.03.x to 2.6.2
After the DCE upgrade, the Image upload field configuration seems wrongly changed (https://nimb.ws/slTyH8). The images are not in those fields and in Frontend the images are present which is the cache.
I have tried changing the old configuration of DCE to the new one. The field is okay now, But the website is refreshed and old images are gone.
I have more than 200 pages. So impossible to reupload. I have uploaded my backup and now I am at the previous state.
Checked the install tool, Unfortunately, there are no Upgrade wizards present for DCE. How can I make it correct without losing images?
Help me!

It is the change from old image handling to FAL-based referencing images. In former versions of DCE, the filename has been saved in tt_content.pi_flexform and there was a predefined/configured path, where this file should be searched. For some time, in TYPO3 files are handled via FAL and so as a relation to an entry of table sys_file...
A few weeks ago, a migrated some DCE elements for a customer. Instead of programming an upgrade-wizard, some lines of PHP were used.
Step 1: Export relevant data
Export the 'uid' of your content elements and filename within your DCE.
For the DCE with UID=2 whre the files field is called "image" this can be done via:
SELECT ExtractValue(pi_flexform, '//field[#index="settings.image"]/value') as filename, `uid`
FROM `tt_content`
WHERE CType='dce_dceuid2' AND ExtractValue(pi_flexform, '//field[#index="settings.image"]/value')!='';
Export the result as CSV.
Step 2: Create releation in sys_file_reference and update tt_content
Now we have to manage the changes to the database:
Create FAL-relations between the DCEs and the sys_file-entries (in form of sys_file_reference-records)
Update the pi_flexform of existing DCE content elements
Update the structure of old-styled DCEs
For these steps, I generated SQL-Queries with a PHP function:
function process(string $csv, string $CType, string $fieldName = 'image'): void
{
foreach (explode(chr(10), $csv) as $line) {
[$fileName, $uid] = explode(';', $line);
if ($fileName && $fileName !== '""') {
$uid = trim($uid);
echo htmlentities("INSERT INTO sys_file_reference (uid_local, uid_foreign, tablenames, fieldname, table_local) VALUES((SELECT uid FROM sys_file WHERE identifier=\"/_migrated_/pics/" . $fileName . "\"), $uid, 'tt_content', '" . $fieldName . "', 'sys_file');",
ENT_QUOTES | ENT_HTML5) . chr(10);
}
}
echo htmlentities('UPDATE tt_content SET pi_flexform=UpdateXML(`pi_flexform`, \'//field[#index="settings.' . $fieldName . '"]/value\', \'<value index=\"vDEF\">1</value>\') WHERE uid=437 AND CType=\'' . $CType . '\' AND ExtractValue(pi_flexform, \'//field[#index="settings.' . $fieldName . '"]/value\')!=\'\';',
ENT_QUOTES | ENT_HTML5) . chr(10);
$configuration = '<config>
<type>inline</type>
<foreign_table>sys_file_reference</foreign_table>
<foreign_field>uid_foreign</foreign_field>
<foreign_sortby>sorting_foreign</foreign_sortby>
<foreign_table_field>tablenames</foreign_table_field>
<foreign_match_fields>
<fieldname>{$variable}</fieldname>
</foreign_match_fields>
<foreign_label>uid_local</foreign_label>
<foreign_selector>uid_local</foreign_selector>
<overrideChildTca>
<columns>
<uid_local>
<config>
<appearance>
<elementBrowserType>file</elementBrowserType>
<elementBrowserAllowed>gif,jpg,jpeg,png</elementBrowserAllowed>
</appearance>
</config>
</uid_local>
</columns>
<types type="array">
<numIndex index="2">
<showitem>--palette--;LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette;imageoverlayPalette,--palette--;;filePalette</showitem>
</numIndex>
</types>
</overrideChildTca>
<minitems>0</minitems>
<maxitems>1</maxitems>
<appearance>
<useSortable>1</useSortable>
<headerThumbnail>
<field>uid_local</field>
<width>45c</width>
<height>45</height>
</headerThumbnail>
<enabledControls>
<info>1</info>
<dragdrop>1</dragdrop>
<hide>1</hide>
<new>0</new>
<sort>0</sort>
<delete>1</delete>
</enabledControls>
<createNewRelationLinkTitle>LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:images.addFileReference</createNewRelationLinkTitle>
</appearance>
<behaviour>
<allowLanguageSynchronization>1</allowLanguageSynchronization>
</behaviour>
<dce_load_schema>1</dce_load_schema>
<dce_get_fal_objects>1</dce_get_fal_objects>
</config>
';
echo 'UPDATE tx_dce_domain_model_dcefield SET configuration=\'' . htmlentities($configuration, ENT_QUOTES | ENT_HTML5) . '\' WHERE variable=\'' . $fieldName . '\' AND parent_dce=' . str_replace('dce_dceuid', '', $CType) . ';' . chr(10);
}
Now, we need to combine the CSV with the code:
$csv = 'image_1.jpg;82
typo3_box.jpg;904';
process($csv, 'dce_dceuid2', 'image');
This will not change anything, but only print out the necessary SQL-queries, which can be reviewed, copied and fired.

Thank you everyone for these detailed explanations.
But We found another method to solve. When analyzing the issue, The Old configuration for the image is having field name as<fieldname>{$bannerimage}</fieldname> And in the database the sys_file_reference table's field name contains the same variable as '{$bannerimage}
What we have done to solve the issue is:
Updated the image configuration to the newest conf and then replaced the <fieldname>{$variable}</fieldname> to <fieldname>bannerimage</fieldname>
The same is done in the DB too. fieldname changed from {$bannerimage} to bannerimage This fixed all problems without losing the image.

Related

How to update the xml attribute values using powershell

I am passing $SourceFileName as studentpackage.zip and copying the zip to below two location.how to update the xml attribute configsolutionfile when there is a change in $SourceFileName
function BuildArchive
{
param
(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[String] $SourceFileName = ""
)
}
D:\StudentProgram\Automate\Publishing\Content\Forums\StudentPackage contains an xml file where I need to update the attribute configsolutionfile
<?xml?>
<config>
<solutions>
<configsolutionfile solutionpackagefilename="studentpackage.zip" />
</solutions>
</config>
D:\StudentProgram\Automate\Publishing\Content\Archives\StudentPackage contains an xml file where I need to update the attribute configsolutionfile
<?xml?>
<config>
<solutions>
<configsolutionfile solutionpackagefilename="studentpackage.zip" />
</solutions>
</config>
You can do this:
[xml]$xml_contents = Get-Content 'path to XML'
$xml_contents.config.solutions.configsolutionfile.solutionpackagefilename = 'test'
$xml_contents.Save('Path to new XML')

Parsing XML and ignoring sections with powershell

I want to parse out the key fields and Data table information from here with PowerShell.
I only want the datatable name if there is a keyfield so in the example below I do not want CC:Attribute.
I also want to output things to a text file.
I want to have a text file that is created that holds the Data table name & Access as well as all the key fields and what they are.
This is the code I have so far:
[xml]$global:xmldata = get-content "C:\hackathon\Mfg.xml"
$xmldata2 = $xmldata.SchemaPackage.Tables
$SField = $xmldata2.DataTable.KeyFields | %{$_.StringField}
$Reffield = $xmldata2.DataTable.KeyFields | %{$_.ReferenceField}
$table = $xmldata2 | %{$_.DataTable}
Xml File:
<?xml version="1.0" encoding="utf-8"?>
<SchemaPackage Namespace="Mfg" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DataTable Name="CC::Attribute">
<DataFields>
</DataFields>
</DataTable>
<DataTable Name="PlannerCode" Access="WW">
<Licenses>Manufacturing, DemandManagement</Licenses>
<Flags>
</Flags>
<KeyFields>
<StringField Name="Value"/>
<ReferenceField Name="Site" Target="Core::Site" SetField="PlannerCodes"/>
</KeyFields>
<DataFields>
<StringField Name="Description"/>
</DataFields>
</DataTable>
</SchemaPackage>
Despite the edit you made, I can only get your XML to validate if I modify it slightly (cleaning the opening XML tag and removing the SchemaPackage namespace). Regardless,
if you're experiencing no issues with your XML import then it's fine.
Here I'm just constructing the XML object from a herestring because I haven't got it in a file on disk.
[xml]$xmldata = #"
<xml>
<DataTable Name="CC::Attribute">
<DataFields>
</DataFields>
</DataTable>
<DataTable Name="PlannerCode">
<Licenses>Manufacturing, DemandManagement</Licenses>
<Flags>
</Flags>
<KeyFields>
<StringField Name="Value"/>
<ReferenceField Name="Site" Target="Core::Site" SetField="PlannerCodes"/>
</KeyFields>
<DataFields>
<StringField Name="Description"/>
</DataFields>
</DataTable>
</xml>
"#
# Filter DataTable nodes for those with a KeyFields child node.
$DataTablesWithKeyFields = $xmldata.xml.DataTable | Where-Object { $_.KeyFields }
$DataTableName = $DataTablesWithKeyFields.Name
$StringFieldData = $DataTablesWithKeyFields.KeyFields.ReferenceField
$ReferenceFieldData = $DataTablesWithKeyFields.KeyFields.ReferenceField
I'm not sure if that's what you're after. $DataTablesWithKeyFields could be an array depending on your XML file so you may need to loop it to extract the information you require.
Since we're working with XML, one of the querying options is XPath!
You can select only DataTable nodes that have a KeyFields child with the following XPath expression:
/SchemaPackage/DataTable[KeyFields]
You can use Select-Xml:
Select-Xml -Path C:\hackathon\Mfg.xml -XPath /SchemaPackage/DataTable[KeyFields] |Select-Object -Expand Node
or pass the expression as an argument to the SelectSingleNodes() method:
[xml]$xmldata = Get-Content C:\hackathon\Mfg.xml
$xmldata.SelectNodes('/SchemaPackage/DataTable[KeyFields]')

How to read value from plugin flexform in TypoScript?

I have a plugin for a custom content element. The plugin contains a flexform. I'd like to use a value from the flexform in my TypoScript setup. How can I do this?
More specifically, the flexform is defined as:
<T3DataStructure>
<meta>
<langDisable>1</langDisable>
</meta>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>LLL:EXT:cb_foundation/Resources/Private/Language/locallang_db.xlf:magellan.sheetTitle</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<settings.magellan.cols>
<TCEforms>
<label>LLL:EXT:cb_foundation/Resources/Private/Language/locallang_db.xlf:magellan.cols</label>
<config>
<type>input</type>
<size>20</size>
<eval>trim</eval>
</config>
</TCEforms>
</settings.magellan.cols>
</el>
</ROOT>
</sDEF>
</sheets>
</T3DataStructure>
My custom element is added to tt_content using the following TypoScript:
lib.cb_foundation.magellan = HMENU
lib.cb_foundation.magellan {
1 = TMENU
1 {
sectionIndex = 1
sectionIndex.type = header
sectionIndex.useColPos = 0
wrap = <div data-magellan-expedition="fixed"><dl class="sub-nav"> | </dl></div>
NO {
allWrap = <dd data-magellan-arrival="c{field:sectionIndex_uid}">|</dd>
allWrap.insertData = 1
}
}
special = list
special.value.data = page:uid
}
tt_content.cbfoundation_magellan =< lib.cb_foundation.magellan
What I want to do is to set tt_content.cbfoundation_magellan.1.sectionIndex.useColPos using the value found in the flexform. How can I do that?
This is not possible. Typoscript does not parse values from a flexform, unfortunately.
You need an extbase controller or pi1 to get the values from the flexform and assign them to a separate template which renders your custom content element.
Extbase Example:
class ContentElementsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
public function YourContentElementAction() {
// Get the data object (contains the tt_content fields)
$data = $this->configurationManager->getContentObject()->data;
// Append flexform values
$this->configurationManager->getContentObject()->readFlexformIntoConf($data['pi_flexform'], $data);
// Assign to template
$this->view->assign('data', $data);
}
}
I dont know, if the extension gridelements or TYPO3 6.2.26 bring the functionality, but the following works for me:
dataWrap = {field:flexform_YOURFIELD}
The following StackOverflow answer describes, how plugin flexform settings of EXT News can be accessed from TS Setup using a small PHP USER Class:
https://stackoverflow.com/a/40006158/430742
It should be easy to adapt for other plugins and their flexform settings.
As stated here there is a solution now in TYPO3 >= 8.4.
The feature is documented in the TYPO3 Core Changelog.

Unable to update a value in msbuild proj file using powershell

I am trying to read a .csproj file using powershell by converting it into xml file to increment WPF app version value. I am able to read the value without any issue and incremented the version value but when I try to save the file with new value, the value doesn't get saved. The code I pasted in this question is to update the QA details.
I am trying to read the below file. How do i update and save file
<Choose>
<When Condition=" '$(BuildEnvironment)' == 'QA' ">
<PropertyGroup>
<ApplicationVersion>1.0.0.1</ApplicationVersion>
<PublishDirectory>C:\TestDirectory</PublishDirectory>
<InstallUrl>http://testurl/testapp</InstallUrl>
<ProductName>Test1.QA</ProductName>
<PublishAssemblyName>Test1.QA</PublishAssemblyName>
</PropertyGroup>
<ItemGroup>
<Tokens Include="ApplicationManifestFileName">
<ReplacementValue>Test1.QA.application</ReplacementValue>
<Visible>false</Visible>
</Tokens>
</ItemGroup>
</When>
<When Condition=" '$(BuildEnvironment)' == 'Production' ">
<PropertyGroup>
<ApplicationVersion>1.0.0.0</ApplicationVersion>
<PublishDirectory>C:\TestDirectory2</PublishDirectory>
<InstallUrl>http://test2url/test2app/</InstallUrl>
<ProductName>Test=2.Prod</ProductName>
<PublishAssemblyName>Test2.Prod</PublishAssemblyName>
</PropertyGroup>
<ItemGroup>
<Tokens Include="ApplicationManifestFileName">
<ReplacementValue>Tes2.Prod.application</ReplacementValue>
<Visible>false</Visible>
</Tokens>
</ItemGroup>
</When>
$Test1QAMSBuildFile = 'C:\Directory\Test.csproj'
[xml]$Test1QABuildVersion = Get-Content $Test1QAMSBuildFile
$CurrentQAVersion= $Test1QABuildVersion.Project.Choose.when.PropertyGroup | ? { $_.ProductName -eq 'Test1.QA' } | Select-Object -Property ApplicationVersion
$PropertyVersion= $CurrentQAVersion.ApplicationVersion
$UpdateVersion= $PropertyVersion.split(".")
$major= [int] ($Updateversion[0])
$minor= [int] ($Updateversion[1])
$patch= [int] ($Updateversion[2])
$revision=[int] ($Updateversion[3])
$newrevisionversion= $revision+1
$newVersion =( [string] $major )+ "."+ ( [string] $minor) +"."+ ([string]$patch ) +"."+ ([string]$newrevisionversion )
$UpdateVersion ="$newVersion"
$TestQABuildVersion.Save("Test1QAMSBuildFile")`
After I added the closing </Choose> I removed .Project from line 3, so you may need to alter what I give you to properly apply to your file.
You never updated $TestQABuildVersion, only some other things that referenced it. What you probably want to do is:
$Test1QAMSBuildFile = 'C:\Directory\Test.csproj'
[xml]$Test1QABuildVersion = Get-Content $Test1QAMSBuildFile
$PropertyVersion = $Test1QABuildVersion.Choose.when.PropertyGroup | ? { $_.ProductName -eq 'Test1.QA' } | Select -Expand ApplicationVersion
$UpdateVersion = $PropertyVersion.split(".")
$UpdateVersion[3] = 1+$UpdateVersion[3]
$newVersion = $UpdateVersion -join "."
$Test1QABuildVersion.Choose.when.PropertyGroup | ? { $_.ProductName -eq 'Test1.QA' } | %{$_.ApplicationVersion = $newVersion}
$TestQABuildVersion.Save($Test1QAMSBuildFile)
Below is code that will work on the example you have given. The main thing you need to keep in mind is that you are dealing with an xml object rather than a powershell object. Selecting the node to be updated requires using SelectSingleNode and specifying an x-path. Using the xml InnerText property allows you to get and set the value. The code below has been tested with the Test.csproj file you provided.
$Test1QAMSBuildFile = 'C:\Directory\Test.csproj'
[xml]$Test1QABuildVersion = Get-Content $Test1QAMSBuildFile
$node = $Test1QABuildVersion.SelectSingleNode("/Choose/When/PropertyGroup/ApplicationVersion[../ProductName = 'Test1.QA']")
$PropertyVersion= $node.InnerText
$UpdateVersion= $PropertyVersion.split(".")
$UpdateVersion[3] = (($UpdateVersion[3] -as [int]) + 1).ToString()
$newVersion = $UpdateVersion -join '.'
$node.InnerText = $newVersion
$Test1QABuildVersion.Save($Test1QAMSBuildFile)
In the case of a real csproj file you will also have to deal with namespaces since the Project element specifies a namespace. I've done bulk modifications to csproj files in the past and it involved quite a learning curve.

Magento: Email template crashes new template form

I have a module that I'm trying to use with an email template I created. I created the .phtml template directly (not through the new template form on the backend) into the locale > en_US > template > email folder. The template seems to work as the variables passed to it work and the email gets sent fine. My only problem is that now when I go into the management > Transactional Emails > New Template, the page crashes. The dropdown is empty and everything after it does't get rendered.
I think it might have something to do with the way I'm loading the template in the modules config.xml. When I remove the reference to the template the problem goes away. Put the reference back in and the form crashes..
Config.xml
<?xml version="1.0"?>
<config>
<modules>
<Optimise_Requestcallback>
<version>0.1.9</version>
</Optimise_Requestcallback>
</modules>
<frontend>
<routers>
<requestcallback>
<use>standard</use>
<args>
<module>Optimise_Requestcallback</module>
<frontName>request-callback</frontName>
</args>
</requestcallback>
</routers>
<layout>
<updates>
<requestcallback>
<file>optimise.xml</file>
</requestcallback>
</updates>
</layout>
</frontend>
<global>
<template>
<email>
<requestcallback_template translate="label" module="requestcallback">
<label>Optimise RequestCallback</label>
<file>requestcallback_template.html</file>
<type>html</type>
</requestcallback_template>
</email>
</template>
</global>
</config>
Here is how I send the email:
public function sendemailAction() {
$emailTemplate = Mage::getModel('core/email_template')
->loadDefault('requestcallback_template');
$emailTemplateVariables = array();
//Fetch submited params
$params = $this->getRequest()->getParams();
$subjectOfMail = "Request a Callback from the Puji Website<br /><br />Product = " . $params['product'] . "<br />Name = " . $params['name'] . "<br />Email = " . $params['email'] . "<br />Telephone = " . $params['telephone'] . "<br />Message = " . $params['comment'];
$emailTemplateVariables['body'] = $subjectOfMail;
$emailTemplate->setSenderName($params['name']);
$emailTemplate->setSenderEmail($params['email']);
try {
$emailTemplate->send('billy#optimiseweb.co.uk', 'Sales', $emailTemplateVariables);
Mage::getSingleton('core/session')->addSuccess('Thank you! We will contact you very soon.');
} catch (Exception $ex) {
$translate->setTranslateInline(true);
Mage::getSingleton('customer/session')->addError(Mage::helper('contacts')->__('Unable to submit your request. Please, try again later'));
$this->_redirect('*/*/');
return;
}
//Redirect back to index action of (this) activecodeline-simplecontact controller
$this->_redirect('request-callback/');
}
And the template itself probably couldn't be any simpler!
<!--#subject Request a Callback from the Puji Website #-->
{{var body}}
Can anyone see an issue here that would cause the New template form to crash?
There can be various reasons, but first check config.xml file for each custom module, one-by-one.
There must be one module, where you will find code like:
module="[some-module-name-here]"
Try removing this code one-by-one and reload the transactional e-mail template form again.
I am sure, it will solve the problem.