Missing image in Typo3 $this->contentObj in 6.0.3 - typo3

in TYPO3 6.0.2 I got an Extbase/Fluid-Extension. The function in the Controller looks like this:
$this->contentObj = $this->configurationManager->getContentObject();
$data = $this->contentObj->data;
print_r($data);
This will return a tt_content - object including image => /path/to/image. Everything fine.
[bodytext] => Lorem ipsum dolor
[image] => ../../fileadmin/user_upload/images/businessman.jpg
Today changing source to TYPO3 6.0.3 everything the same but the image is just a "1".
[bodytext] => Lorem ipsum dolor
[image] => 1
What can I do? Thanks!

i found this to get files without sql query
public function myAction(){
// get data of the content object
$data = $this->contentObj = $this->configurationManager->getContentObject()->data;
// Neu ab Typo3 6.0.3 -> Bild in tt_content-Object wird nicht mehr mit zurueckgeliefert, daher:
$fileRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\FileRepository');
$fileObjects = $fileRepository->findByRelation('tt_content', 'image', $data['uid']);
$files = array();
foreach ($fileObjects as $key => $value) {
$files[$key]['reference'] = $value->getReferenceProperties();
$files[$key]['original'] = $value->getOriginalFile()->getProperties();
}
#t3lib_utility_Debug::debug($files);
#die('Ende');
// Files in Fluid ausgeben
$this->view->assign('files', $files);
// Daten in Fluid ausgeben
$this->view->assign('data', $data);
}
fluid
<f:for each="{files}" as="file">
<li>
<img src="fileadmin{file.original.identifier}" alt="" />
<p class="flex-caption"><f:format.nl2br>{file.reference.description}</f:format.nl2br></p>
</li>
</f:for>

the bug appears to be a result of the security update where the typical jumpURL system has changed (SQL Injection). I filed a bug here: http://forge.typo3.org/issues/46090

Since TYPO3 6 the method "function getContentObject($name)" was located in
*typo3\sysext\cms\tslib\class.tslib_content.php*.
Content of this file:
/*
* #deprecated since 6.0, the classname tslib_cObj and this file is obsolete
* and will be removed with 6.2. The class was renamed and is now located at:
* typo3/sysext/frontend/Classes/ContentObject/ContentObjectRenderer.php
*/
require_once \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('frontend') . 'Classes/ContentObject/ContentObjectRenderer.php';
But I don't see any differences between the old an the new file containing my problem.
I didn't find out how to get the file reference for the tt_content-entry "native", so I wrote a SQL-query:
public function bla() {
// get data of the content object
$this->contentObj = $this->configurationManager->getContentObject();
$data = $this->contentObj->data;
// Neu ab Typo3 6.0.3 -> Bild in tt_content-Object wird nicht mehr mit zurueckgeliefert, daher:
// https://forge.typo3.org/issues/46090
// http://stackoverflow.com/questions/15250351/missing-image-in-typo3-this-contentobj-in-6-0-3
$res = $GLOBALS['TYPO3_DB']->sql_query(
'select sys_file.identifier from sys_file_reference left join sys_file on sys_file_reference.uid_local = sys_file.uid where sys_file_reference.uid_foreign='.$data['uid'].' and sys_file_reference.deleted=0'
);
while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
$data['image'] = $row['identifier'];
}
#print_r($data);
// assign the data to the fluid template
$this->view->assign('data', $data);
}

Related

Zend : Error Occurs when create html file from zend phtml file for multiple employee

//controller function
function sendBulkMailAction(){
$template = "estimated-festival-bill-single.phtml";
foreach ($employeeArr as $profile_id => $employeeValue) {
$someData = array(); //here include some salary data
$model = new ViewModel($someData);
$model->setTemplate($template);
$htmlContent = "<!DOCTYPE html>\n\r<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\r<head>
<meta charset=\"utf-8\">
</head>
<body>"
. $this->getServiceLocator()->get('viewrenderer')->render($model)
. "</body>
</html>";
//create html file
//create pdf link from html by wkhtmlToPdf
//send this link via email to employee
}
}
//estimated-festival-bill-single.phtml
//simple code
<div> Employee Name</div>
<br>
<div><?php echo _get_salary_html(); ?></div>
<?php
function _get_salary_html(){
return "Salary Data";
}
?>
error show
Fatal error: Cannot redeclare _get_salary_html() (previously declared in G:\xampp\htdocs\ums\module\Hrm\view\hrm\salary-reports\estimated-salary-bill-single.phtml:9) in G:\xampp\htdocs\ums\module\Hrm\view\hrm\salary-reports\estimated-salary-bill-single.phtml on line 10
hints: when single employee its ok but for multiple employee show error
Because you are re-declaring function unknowingly. Add a condition around the function like below.
if (!function_exists('_get_salary_html')) {
function _get_salary_html() {
........
}
}

How to replace src with data-src in TYPO3's YouTube iframe tag?

In order to use the "Klaro! Consent Manager" I need to modify the iframe-tag a little bit, which is automatically generated by TYPO3 when you embed a YouTube video with a textmedia element.
It is generated in /typo3/sysext/core/Classes/Resource/Rendering/YouTubeRenderer.php
public function render(FileInterface $file, $width, $height, array $options = [], $usedPathsRelativeToCurrentScript = false)
{
$options = $this->collectOptions($options, $file);
$src = $this->createYouTubeUrl($options, $file);
$attributes = $this->collectIframeAttributes($width, $height, $options);
return sprintf(
'<iframe src="%s"%s></iframe>',
htmlspecialchars($src, ENT_QUOTES | ENT_HTML5),
empty($attributes) ? '' : ' ' . $this->implodeAttributes($attributes)
);
}
I already have a user_site extension to configure the system and edit the templates, but without any php classes. It looks like I can't just overwrite a fluid template here. I'm an integrator, not an extension developer, and i wonder how i can overwrite or extend this function accordingly, without changing or duplicating too much of the core functions.
How can I replace <iframe src= with <iframe data-name="youtube" data-src=?
Thanks to the comment from nstungcom I have found good samples in the extension media2click and was able to modify the iFrame tag with fragments of this. Since I am not an extension developer, this solution should be used with caution until it is confirmed by a developer. Suggestions for improvement are very appreciated.
I made the following changes / additions to my sitepackage ("user_site" extension):
/ext/user_site/Classes/Resource/Rendering/YouTubeRenderer.php
<?php
namespace MyVendorName\UserSite\Resource\Rendering;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Resource\FileInterface;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
class YouTubeRenderer extends \TYPO3\CMS\Core\Resource\Rendering\YouTubeRenderer
{
public function getPriority()
{
return 25;
}
public function render(FileInterface $file, $width, $height, array $options = [], $usedPathsRelativeToCurrentScript = false)
{
$options = $this->collectOptions($options, $file);
$iframe = str_replace(' src="', ' src="" data-name="youtube" data-src="', parent::render($file, $width, $height, $options, $usedPathsRelativeToCurrentScript));
return $iframe;
}
}
I'm uncertain if all of those use statements and the getPriority function are really necessary.
/ext/user_site/ext_localconf.php
<?php
defined('TYPO3_MODE') or die();
call_user_func(function () {
$rendererRegistry = \TYPO3\CMS\Core\Resource\Rendering\RendererRegistry::getInstance();
$rendererRegistry->registerRendererClass(\MyVendorName\UserSite\Resource\Rendering\YouTubeRenderer::class);
});
I do not know if this is a so-called XCLASS. The syntax looks different from what I found as an example in the Api.
/ext/user_site/ext_emconf.php
<?php
$EM_CONF[$_EXTKEY] = [
'title' => 'Project specific configuration and templates',
// [...]
'autoload' => [
'psr-4' => [
'MyVendorName\\UserSite\\' => 'Classes',
],
],
];
Apparently it needed this autoload, whatever that's for.

Find and extract content of division of certain class using DomXPath

I am trying to extract and save into PHP string (or array) the content of a certain section of a remote page. That particular section looks like:
<section class="intro">
<div class="container">
<h1>Student Club</h1>
<h2>Subtitle</h2>
<p>Lore ipsum paragraph.</p>
</div>
</section>
And since I can't narrow down using class container because there are several other sections of class "container" on the same page and because there is the only section of class "intro", I use the following code to find the right division:
$doc = new DOMDocument;
$doc->preserveWhiteSpace = FALSE;
#$doc->loadHTMLFile("https://www.remotesite.tld/remotepage.html");
$finder = new DomXPath($doc);
$intro = $finder->query("//*[contains(#class, 'intro')]");
And at this point, I'm hitting a problem - can't extract the content of $intro as PHP string.
Trying further the following code
foreach ($intro as $item) {
$string = $item->nodeValue;
echo $string;
}
gives only the text value, all the tags are stripped and I really need all those divs, h1 and h2 and p tags preserved for further manipulation needs.
Trying:
foreach ($intro->attributes as $attr) {
$name = $attr->nodeName;
$value = $attr->nodeValue;
echo $name;
echo $value;
}
is giving the error:
Notice: Undefined property: DOMNodeList::$attributes in
So how could I extract the full HTML code of the found DOM elements?
I knew I was so close... I just needed to do:
foreach ($intro as $item) {
$h1= $item->getElementsByTagName('h1');
$h2= $item->getElementsByTagName('h2');
$p= $item->getElementsByTagName('p');
}

TYPO3: How to render translated content in extension

I am developing a TYPO3 6.0 plugin that shows the subpages of the current page as tabs. For example, on the following pages my plugin is inserted on TabRoot:
If TabRoot is requested, the plugin's ActionController looks up the database for the subpage titles and contents and passes all gathered data to a Fluid template. The page is then rendered like the following:
With JS in place I always hide/show content below based on the selection. My problem is that I want to show the translated content of the subpages based on the current language selection. How am I able to do this? I've tried it with several methods, but neither of them was flawless. These are the methods I've tried:
Using RECORDS This method is not affected by the selected language, it always returns the content in the default language:
//Get the ids of the parts of the page
$select_fields = "uid";
$from_table = "tt_content";
$where_clause = 'pid = ' . $pageId;
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
$select_fields,
$from_table,
$where_clause,
$groupBy='',
$orderBy='sorting',
$limit=''
);
$ids = '';
$firstIteration = true;
while ( $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc( $res ) ) {
if (!$firstIteration) $ids .= ",";
$ids .= $row ['uid'];
$firstIteration = false;
}
$GLOBALS['TYPO3_DB']->sql_free_result( $res );
//Render the parts of the page
$conf ['tables'] = 'tt_content';
$conf ['source'] = $ids;
$conf ['dontCheckPid'] = 1;
$content = $this->cObj->cObjGetSingle ( 'RECORDS', $conf );
Using CONTENTS According to TYPO3: How to render localized tt_content in own extension, this is the way to do it, however for me this also returns the content rendered with the default language. It is not affected by a language change.
$conf = array(
'table' => 'tt_content',
'select.' => array(
'pidInList' => $pageId,
'orderBy' => 'sorting',
'languageField' => 'sys_language_uid'
)
);
$content = $this->cObj->cObjGetSingle ( 'CONTENT', $conf );
Using VHS: Fluid ViewHelpers I installed the vhs extension and tried to render the content with <v:content.render />. The result is the same as with CONTENTS; it only works with the default language.
{namespace v=Tx_Vhs_ViewHelpers}
...
<v:content.render column="0" order="'sorting'" sortDirection="'ASC'"
pageUid="{pageId}" render="1" hideUntranslated="1" />
Using my own SQL query I've tried to get the bodytext fields of the page and then render those with \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_RTEcssText(). This method returns the content based on the current language, however the problem is that bodytext's do not contain the complete content (images, other plugins, etc).
$select_fields = "bodytext";
$from_table = "tt_content";
$where_clause = 'pid = ' . $pageId
. ' AND sys_language_uid = ' . $GLOBALS ['TSFE']->sys_language_uid;
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
$select_fields,
$from_table,
$where_clause,
$groupBy='',
$orderBy='sorting',
$limit=''
);
$content = '';
while ( $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc( $res ) ) {
$content .=
\TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_RTEcssText( $row ['bodytext'] );
}
$GLOBALS['TYPO3_DB']->sql_free_result( $res );
What am I missing? Why isn't the content rendered with the current language in the case of the CONTENTS method?
Easiest way is to use the cObject viewhelper to render right from TypoScript.
And inside your TypoScript template provide the configuration:
lib.myContent = CONTENT
lib.myContent {
...
}
BTW, you are bypassing the TYPO3 CMS API. Please do not do so. Always use the API methods to query for data.
e.g. \TYPO3\CMS\core\Database\DatabaseConnection is always available at GLOBALS['TYPO3_DB']->. Do not use the the mysql function.
On top of that, I believe that you can archive whatever you are trying to do with pure TypoScript, without the need to program anything. Feel free to ask a new questions to get help on this.
In TYPO3 4.x you could use the following methods to load the translated record:
t3lib_pageSelect->getRecordOverlay
t3lib_pageSelect->getPageOverlay
They are also available at $GLOBALS['TSFE']->sys_page->getRecordOverlay().

Zend Form Element Row needs either an id or class set through Zend_Config_Ini

I have the following default decorators in a Zend_Config_Ini to set up my form:
elementDecorators.viewHelper.decorator = "ViewHelper"
elementDecorators.label.decorator = "Label"
elementDecorators.errors.decorator = "Errors"
elementDecorators.htmlTag.decorator = "HtmlTag"
elementDecorators.htmlTag.options.tag = "li"
I have the following element definition also in the Zend_Config_Ini:
elements.username.type = "text"
elements.username.options.label = "Username:"
elements.username.options.required = true
and the following output is produced:
<li>
<label for="username" class="required">Username:</label>
<input type="text" name="username" id="username" value="" />
</li>
Now what I need to know is, how do I (through the ini config file preferably), set the id or class of the LI tag? I would like the following output:
<li id="form-username-element"> ... </li>
or
<li class="form-2col"> ... </li>
Update:
I was able to get it by overriding all the decorators in the element config itself like this:
elements.username.options.decorators.viewHelper.decorator = "ViewHelper"
elements.username.options.decorators.label.decorator = "Label"
elements.username.options.decorators.errors.decorator = "Errors"
elements.username.options.decorators.htmlTag.decorator = "HtmlTag"
elements.username.options.decorators.htmlTag.options.tag = "li"
elements.username.options.decorators.htmlTag.options.class = "username-row-element"
So that will work, however creates a lot of duplication as that would have to go onto every element (with the single change of the last line which would be the class setting itself). So what I am NOW wondering, is, from the ini file, is there a way to just override the class name using the default decorators (rather than having to duplicate all of the decorators for each element)?
Easiest thing to do is create your own Decorator. For instance, I've created an ElementWrap decorator, which wraps each element with a div and adds the necessary class and id. It could look something like this:
class Form_Decorator_ElementWrap extends Zend_Form_Decorator_Abstract
{
public function render($content)
{
$element = $this->getElement();
if($this->getOption('openOnly')) {
return '<div class="'.$this->getClass().'" id="'.$this->getId().'">' . $content;
} else if($this->getOption('closeOnly')) {
return $content . PHP_EOL . '</div>' . PHP_EOL;
} else {
return '<div class="'.$this->getClass().'" id="'.$this->getId().'">' . $content . '</div>';
}
}
public function getClass()
{
$element = $this->getElement();
$classes = array(
'field_wrap',
'field_' . strtolower(substr(strrchr($element->getType(), '_'), 1)),
$this->getOption('class'),
);
if($element->hasErrors()) {
$classes[] = 'field_error';
}
if($elementClass = $element->getAttrib('class')) {
$classes[] = $elementClass;
}
return implode(' ', array_filter($classes));
}
public function getId()
{
return 'fieldwrap-' . $element->getId();
}
}