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

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.

Related

Viewhelper Class not found when loaded from Cache. First request work

I have created a view helper in TPYO3 11.
<?php
namespace DN\RisaProjects\Viewhelpers;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
class TestViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
protected $escapeOutput = false;
public function initializeArguments()
{
// registerArgument($name, $type, $description, $required, $defaultValue, $escape)
$this->registerArgument('test', 'string', 'test', true);
}
public static function renderStatic(
array $arguments,
\Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
)
{
return $arguments['test'];
}
}
The namespace is registered in ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['rp'] = [
'DN\RisaProjects\ViewHelpers',
];
In the Fluid template I use it like this
<rp:test test="hallo" />
As far as how I have always done it so far. The first call also works. But when the page is loaded from the cache, the viewhelper class is no longer found.
Fluidcache File:
$output0 .= DN\RisaProjects\Viewhelpers\TestViewHelper::renderStatic($arguments36, $renderChildrenClosure37, $renderingContext);
Class "DN\RisaProjects\Viewhelpers\TestViewHelper" not found
What could be the reason for that? I have checked the syntax several times and the autoload files are also correct. The first call also works.

Is it possible to hide form from non-registered users?

I need to hide form with some shortcode [contact-form-7 id="3080"] from non-registered users in WordPress.
So i've tried to use inserted tags like this '[client][contact-form-7 id="3080"][/client]' and it doesn't work.
with this php code
function access_check_shortcode( $attr, $content = null ) {
extract( shortcode_atts( array( 'capability' => 'read' ), $attr ) );
if ( current_user_can( $capability ) && !is_null( $content ) && !is_feed() )
return $content;
return '';
}
add_shortcode( 'access', 'access_check_shortcode' );
This one isn't interesting, cause i need to show it inside the template
<?php
if ( is_user_logged_in() )
echo do_shortcode( '[contact-form-7 id="1234" title="Contact form 1"]' );
?>
Are you willing/able to install third party plugins? If so, you might want to check out either or both of these:
Hide This (https://wordpress.org/plugins/hide-this/)
Eyes Only (https://bs.wordpress.org/plugins/eyes-only-user-access-shortcode/)
Both of these work by enabling shortcode that can be wrapped around specific content. I believe both have options to how only to logged-in users.

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().

Joomla plugin not being called

This is my 1st time I'm attempting to create a Joomla plugin and I need some help on getting this to work. The plugin is quite simple, I want to capture the HTTP_REFERER, check if the request was made from Google organic or paid results, pass the data to a session var and then submit it along with the values in a contact form. (there's a hidden field in my form and it gets the session var value). I use RSForms for creating my forms, just for the reference.
In the beginning, I hardcoded the following code into index.php at site root and it worked fine. Now, I'm trying to make a proper plugin but I can't get it to fire off when pages are loaded. I've tried all the system methods, still failing to get it to run.
This is my code:
defined( '_JEXEC' ) or die( 'Restricted access' );
jimport( 'joomla.plugin.plugin' );
class plgSystemRsformsGoogleReferer extends JPlugin
{
public function plgSystemRsformsGoogleReferer( &$subject, $config )
{
parent::__construct( $subject, $config );
}
function onAfterRender()
{
$session = & JFactory::getSession();
if (!$session->get('referrer', $origref, 'extref')) //If does not exist
{
$origref = $_SERVER['HTTP_REFERER'];
$session->set('referrer', $origref, 'extref');
$q = search_engine_query_string($session->get('referrer', $origref, 'extref'));
if(stristr($origref, 'aclk')) { // if referer is a google adwords link as opposed to an organic link
$type = ', paid link';
} else {
$type = ', organic result';
}
$ginfo = $q.$type;
$session->set('referrer', $ginfo, 'extref');
}
function search_engine_query_string($url = false) {
if(!$url && !$url = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : false) {
return '';
}
$parts_url = parse_url($url);
$query = isset($parts_url['query']) ? $parts_url['query'] : (isset($parts_url['fragment']) ? $parts_url['fragment'] : '');
if(!$query) {
return '';
}
parse_str($query, $parts_query);
return isset($parts_query['q']) ? $parts_query['q'] : (isset($parts_query['p']) ? $parts_query['p'] : '');
}
}
}
And this is my manifest xml for the plugin installation (installation works fine):
<?xml version="1.0" encoding="utf-8"?>
<install version="1.5" type="plugin" group="system" method="upgrade">
<name>RSForm Google Referer v1.1</name>
<author>Me</author>
<creationDate>July 2012</creationDate>
<copyright>(C) 2004-2012 www.mysite.com</copyright>
<license>Commercial</license>
<authorEmail>info#mysite.com</authorEmail>
<authorUrl>www.mysite.com</authorUrl>
<version>1.1</version>
<description><![CDATA[Track visitor's search terms and and attaches the information to the RSForm! Pro Forms emails when sent.]]></description>
<files>
<filename plugin="rsform_google_referer">rsform_google_referer.php</filename>
</files>
</install>
I feel I'm close but I can't get it to run, any suggestions will be appreciated. Thanks!
The name of the class is wrong. It needs to match the name of the plugin folder and that name of the plugin file. It should be:
class plgSystemRsform_Google_Referer extends JPlugin
That is Rsform not Rsforms and the underscores.

How can I make a Zend Decorator to allow a default value?

I want a basic:
<input type="text" />
And I would like the default value to clear when the user puts in a value (kinda like this). It would be ideal if the default value returned onBlur.
I don't want the default value to be submitted if they leave it and click submit.
I'm generating the form using Zend, and imagine my solution can fit entirely into a Zend Form Decorator.
I can't find any existing ones, so I ask:
Do you have said decorator? Or something that will help me make one?
Just use corresponding jQuery plugins: defaultvalue
Ok, I've built a decorator which allows me to implement the jquery plugin Ololo posted.
It checks to see if the element has a Label set, and if it does, defaults to that:
require_once 'Zend/Form/Decorator/Abstract.php';
class Application_Form_Decorator_DefaultEnabledInput extends Zend_Form_Decorator_Abstract
{
private $attribs = array();
public function render($content)
{
$element = $this->getElement();
if(get_class($element) != 'Zend_Form_Element_Text') throw new Exception("Application_Form_Decorator_DefaultEnabledInput only works on text fields");
$element->setAttrib('type', 'text');
$element->setAttrib('name', htmlspecialchars($element->getName()));
$element->setAttrib('value', htmlspecialchars($element->getValue()));
$attribs = '';
$default = $element->getLabel();
if($default)
{
$element->setAttrib('rel', $default);
$element->setAttrib('title', $default);
$class = $element->getAttrib('class');
$element->setAttrib('class', "$class hasDefault");
$default = "";
}
foreach($element->getAttribs() as $key => $val) $attribs .= "$key='$val' ";
return "<input $attribs/>";
}
}
It allows me to define a default value in the form object (using setLabel).
$element = $this->createElement('text', 'suburb');
$element->setDecorators(array('DefaultEnabledInput'));
$element->setLabel('enter suburb here');
$this->addElement($element);
And all I need to do then is ensure that query and plugin are included on the page, and this piece of code:
$(document).ready(function() {
// default values
$('.hasDefault').each(function(){
$(this).defaultValue();
});
});
Then in the template, I can display the object like this:
<?= $this->form->getElement('suburb') ?>