Translation in extension fails when not logged into backend - typo3

I have an extbase extension that translates some variables on pages using this
if (is_array($row) && $row['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content && $GLOBALS['TSFE']->sys_language_contentOL) {
$row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($table, $row,$GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
}
But there's a strange bug. It only works, when I'm logged into the backend. As soon as I log out, I can only see the default language.
Using Typo3 8.7
Any ideas what this could cause?

This can happen if you have config.sys_language_overlay = 0 defined globaly on your page object within your Typoscript Setup.
There is a ticket entry in the Typo3 Forge that goes a bit deeper as to why this happens and provides some workarrounds if you need those.

So, I didn't figure out what the problem was, but found my own workaround for the problem. Here's the updated Code:
$table = 'tx_myExt';
$query = "SELECT * FROM ".$table." WHERE pid=".$pid;
$query .= ' AND (sys_language_uid IN (-1,0) OR (sys_language_uid = ' .$GLOBALS['TSFE']->sys_language_uid. ' AND l10n_parent = 0))';
$query .= " AND deleted=0 AND hidden=0";
$res = $GLOBALS['TYPO3_DB']->sql_query($query);
while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
//localization
// check for language overlay if:
// * row is valid
// * row language is different from currently needed language
// * sys_language_contentOL is set
if (is_array($row) && $row['sys_language_uid'] != $GLOBALS['TSFE']->sys_language_content && $GLOBALS['TSFE']->sys_language_contentOL) {
$query2 = "SELECT * FROM ".$table." WHERE pid=".$pid;
$query2 .= ' AND sys_language_uid = ' .$GLOBALS['TSFE']->sys_language_content;
$query2 .= ' AND l10n_parent = ' . $row['uid'];
$query2 .= " AND deleted=0 AND hidden=0";
$res2 = $GLOBALS['TYPO3_DB']->sql_query($query2);
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res2);
//$row = $GLOBALS['TSFE']->sys_page->getRecordOverlay($table, $row,$GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
}
}
So, instead of using getRecordOverlay I'm just repeating the query, accessing the translated record directly. I did read somewhere that this is bad practice, but hey, it works for now, that's all that matters ;)
Still, if someone finds a solution to the original problem, I'd be happy to see that.

Related

Allowing multiple choices instead of just one

I have a code that is used for adding a channel to an IPTV platform!
Currently we have the option to put a channel in single category/genre... What we want to do is instead of this drop box to a have something like checklist or space to write the genres/categories... I have tried everything I remembered I knew, but nothing worked! Thank you
function get_genres() {
global $tv_genre_id;
$genres = Mysql::getInstance()->from('tv_genre')->get()->all();
$option = '';
foreach ($genres as $arr){
$selected = '';
if ($tv_genre_id == $arr['id']){
$selected = 'selected';
}
$option .= "<option value={$arr['id']} $selected>"._($arr['title'])."\n";
}
return $option;
}

How correctly to use the snippet() function?

My first Sphinx app almost works!
I successfully save path,title,content as attributes in index!
But I decided go to SphinxQL PDO from AP:
I found snippets() example thanks to barryhunter again but don't see how use it.
This is my working code, except snippets():
$conn = new PDO('mysql:host=ununtu;port=9306;charset=utf8', '', '');
if(isset($_GET['query']) and strlen($_GET['query']) > 1)
{
$query = $_GET['query'];
$sql= "SELECT * FROM `test1` WHERE MATCH('$query')";
foreach ($conn->query($sql) as $info) {
//snippet. don't works
$docs = array();
foreach () {
$docs[] = "'".mysql_real_escape_string(strip_tags($info['content']))."'";
}
$result = mysql_query("CALL SNIPPETS((".implode(',',$docs)."),'test1','" . mysql_real_escape_string($query) . "')",$conn);
$reply = array();
while ($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
$reply[] = $row['snippet'];
}
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print( $output . "<br><br>");
}
}
I have got such structure from Sphinx index:
Array
(
[0] => Array
(
[id] => 244
[path] => DOC7000/zdorovie1.doc
[title] => zdorovie1.doc
[content] => Stuff content
I little bit confused with array of docs.
Also I don't see advice: "So its should be MUCH more efficient, to compile the documents and call buildExcepts just once.
But even more interesting, is as you sourcing the the text from a sphinx attribute, can use the SNIPPETS() sphinx function (in setSelect()!) in the main query. SO you dont have to receive the full text, just to send back to sphinx. ie sphinx will fetch the text from attribute internally. even more efficient!
"
Tell me please how I should change code for calling snippet() once for docs array, but output path (link), title for every doc.
Well because your data comes from sphinx, you can just use the SNIPPET() function (not CALL SNIPPETS()!)
$query = $conn->quote($_GET['query']);
$sql= "SELECT *,SNIPPET(content,$query) AS `snippet` FROM `test1` WHERE MATCH($query)";
foreach ($conn->query($sql) as $info) {
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
print("$output<br>{$info['snippet']}<br><br>");
}
the highlighted text is right there in the main query, dont need to mess around with bundling the data back up to send to sphinx.
Also shows you should be escaping the raw query from user.
(the example you found does that, because the full text comes fom MySQL - not sphinx - so it has no option but to mess around sending data back and forth!)
Just for completeness, if REALLY want to use CALL SNIPPETS() would be something like
<?php
$query =$conn->quote($_GET['query']);
//make query request
$sql= "SELECT * FROM `test1` WHERE MATCH($query)";
$result = $conn->query($sql);
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
//build list of docs to send
$docs = array();
foreach ($rows as $info) {
$docs[] = $conn->quote(strip_tags($info['content']));
}
//make snippet reqest
$sql = "CALL SNIPPETS((".implode(',',$docs)."),'test1',$query)";
//decode reply
$reply = array();
foreach ($conn->query($sql) as $row) {
$reply[] = $row['snippet'];
}
//output results using $rows, and cross referencing with $reply
foreach ($rows as $idx => $info) {
// path, title out. works
$path = rawurlencode($info["path"]); $title = $info["title"];
$output = '<a href=' . $path . '>' . $title . '</a>'; $output = str_replace('%2F', '/', $output);
$snippet = $reply[$idx];
print("$output<br>$snippet<br><br>");
}
Shows putting the rows into an array, because need to lopp though the data TWICE. Once to 'bundle' up the docs array to send. Then again to acully display rules, when have $rows AND $reply both available.

Joomla: get all users in a usergroup

I am working on a component where I want to show all users of a specific usergroup. Right now I found two solutions for this but I'm not feeling comfortable with both of them.
Solution 1
$usersID = JAccess::getUsersByGroup(3);
$users = array();
foreach($usersID as $cUserID)
{
$users[] = JFactory::getUser($cUserID);
}
This one seems to produce two database queries every time JFactory::getUser($cUserID) is called. I really don't want this.
Solution 2
function inside model
function getUsers()
{
if(!isset($this->users))
{
$groupID = 3;
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$select = array( 'users.id', 'users.name');
$where = $db->quoteName('map.group_id') . ' = ' . $groupID;
$query
->select($select)
->from( $db->quoteName('#__user_usergroup_map', 'map') )
->leftJoin( $db->quoteName('#__users', 'users') . ' ON (map.user_id = users.id)' )
->where($where);
$db->setQuery($query);
$this->users = $db->loadObjectList();
}
return $this->users;
}
This one works like a charm but I feel there should be a "more Joomla! way" of doing this. I don't like working on their tables.
Right now I'm going with solution 2 but i really wonder if there is some better way to do it.

Prepare content does not work for Sourcerer and DirectPHP

In my Joomla website, I need to execute some custom SQL queries, that have to select different titles from related categories.
Problem I have it works like option Prepare Content is turned off, so all of my content is outside HTML tags.
Module content looks like this:
{source}
<?php
$var_result = '';
$var_categories = array();
$var_category_list = array();
$db =& JFactory::getDBO();
$query = 'select * from jneg_categories where parent_id = 9';
$db->setQuery($query,0,300);
$res = $db->loadObjectList();
foreach ( $res as $row ) {
$var_categories[($row->id)] = $row->title;
$var_category_list[] = $row->id;
}
$var_category_list = implode($var_category_list, ', ');
$sql = "select * from jneg_content where catid IN (".$var_category_list.") order by `catid`";
$db->setQuery($sql,0,30000);
$res = $db->loadObjectList();
$var_current_cat = 0;
foreach ( $res as $row ) {
if ($current_cat != $row->catid) {
$current_cat = $row->catid;
echo '<h2>'.$categories[($row->catid)] . '</h2>';
echo '<br>';
}
echo $row->title;
echo '<br>';
}
?>
{/source}
Can you help me how to get proper HTML as a result of this code please.
Sourcer or other php rendering plugins don't run in html modules unless you go under the module 'options' and select 'prepare content'...
...or you can use this module and just include your php file directly:
https://github.com/idea34/mod_show
Ok, I did it with Jumi plugin - http://2glux.com/projects/jumi/usage-for-j15
Thank you anyway.

strip_tags or preg_replace to remove few tags from html?

I am in dilemma between these two.
I want to strip head tags ( and everything inside/before including doctype/html) , body tag and script tags from a page that I am importing via curl.
So first thought was this
$content = strip_tags($content, '<img><p><a><div><table><tbody><th><tr><td><br><span><h1><h2><h3><h4><h5><h6><code><pre><b><strong><ol><ul><li><em>'.$tags);
which as you can see can get even longer with HTML5 tags, video object etc..
Than I saw this here.
https://stackoverflow.com/a/16377509/594423
Can anyone advise the preferred method or show your way of doing this and please explain why and
possibly tell me which one is faster.
Thank you!
You can test something like that:
$dom = new DOMDocument();
#$dom->loadHTML($content);
$result = '';
$bodyNode = $dom->getElementsByTagName('body')->item(0);
$scriptNodes = $bodyNode->getElementsByTagName('script');
$toRemove = array();
foreach ($scriptNodes as $scriptNode) {
$toRemove[] = $scriptNode;
}
foreach($toRemove as $node) {
$node->parentNode->removeChild($node);
}
$bodyChildren = $bodyNode->childNodes;
foreach($bodyChildren as $bodyChild) {
$result .= $dom->saveHTML($bodyChild);
}
The advantage of the DOM approach is a relative reliability against several html traps, especially some cases of malformed tags, or tags inside javascript strings: var str = "<body>";
But what about speed?
If you use a regex approach, for example:
$pattern = <<<'EOD'
~
<script[^>]*> (?>[^<]++|<(?!/script>))* </script>
|
</body>.*$
|
^ (?>[^<]++|<(?!body\b))* <body[^>]*>
~xis
EOD;
$result = preg_replace($pattern, '', $content);
The result is a little faster (from 1x to 2x for an html file with 400 lines). But with this code, the reliability decreases.
If speed is important and if you have a good idea of the html quality, for the same reliability level than the regex version, you can use:
$offset = stripos($content, '<body');
$offset = strpos($content, '>', $offset);
$result = strrev(substr($content,++$offset));
$offset = stripos($result, '>ydob/<');
$result = substr($result, $offset+7);
$offset = 0;
while(false !== $offset = stripos($result, '>tpircs/<', $offset)) {
$soffset = stripos($result, 'tpircs<', $offset);
$result = substr_replace($result, '', $offset, $soffset-$offset+7);
}
$result = strrev($result);
That is between 2x and 5x faster than the DOM version.