I'm writing my own component for Joomla 1.5. I'm trying to figure out how to generate an "alias" (friendly URL slug) for the content I add. In other words, if the title is "The article title", Joomla would use the-article-title by default (you can edit it if you like).
Is there a built-in Joomla function that will do this for me?
Line 123 of libraries/joomla/database/table/content.php implements JFilterOutput::stringURLSafe(). Pass in the string you want to make "alias friendly" and it will return what you need.
If you are trying to generate an alias for your created component it is very simple. Suppose you have click on save or apply button in your created component or suppose you want to make alias through your tile, then use this function:
$ailias=JFilterOutput::stringURLSafe($_POST['title']);
Now you can insert it into database.
It's simple PHP.
Here is the function from Joomla 1.5 source:
Notice, I have commented the two lines out. You can call the function like
$new_alias = stringURLSafe($your_title);
function stringURLSafe($string)
{
//remove any '-' from the string they will be used as concatonater
$str = str_replace('-', ' ', $string);
$str = str_replace('_', ' ', $string);
//$lang =& JFactory::getLanguage();
//$str = $lang->transliterate($str);
// remove any duplicate whitespace, and ensure all characters are alphanumeric
$str = preg_replace(array('/\s+/','/[^A-Za-z0-9\-]/'), array('-',''), $str);
// lowercase and trim
$str = trim(strtolower($str));
return $str;
}
Related
I'm trying to make my test app in multilanguage way.
This question has two correlated questions:
First question:
I followed the second answer in How to create multilingual translated routes in Laravel and this help me having a multilanguage site and the route cached, but I've a question and some misunderstanding.
It's a good practice overwrite an app config as they do int the AppServiceProver.php, making:
Config::set('app.locale_prefix', Request::segment(1));
Isn't better to work with the Session::locale in any case?
Second question:
In my case I've two languages, and in the navbar I want to print just ENG when locale is original language, and ITA when session locale is English.
If I'm in the Italian page, the ENG link in the navbar should point to the same English translated page.
Working with the method used in the other question, I hade many problems caused by the:
Config::set('app.locale_prefix', Request::segment(1));
We overwrite the variable in the config file local_prefix, and every time I switch to English language the locale_prefix will change to 'eng' and this sounds me strange, another thing I did is this:
if ( $lang && in_array($lang, config('app.alt_langs')) ){
return app('url')->route($lang . '_' . $name, $parameters, $absolute);
}
We use the alt_langs where are defined only the alternative languages, and this is a problem cause if I pass the local lang, in my case 'it', like lang parameter, this will not be found cause, from the description, the alt_lang should not contain the locale language and you will be able to get only the translated string.
If I change the:
if ( $lang && in_array($lang, config('app.alt_langs')) ){
return app('url')->route($lang . '_' . $name, $parameters, $absolute);
}
in:
if ( $lang && in_array($lang, config('app.all_langs')) ){
return app('url')->route($lang . '_' . $name, $parameters, $absolute);
}
Now using app.all_langs I'm able to choose which URL you want and in which language I want.
How do I get the translated URL?
In the blade file I need to get the translated URL of the page, and if read the other question, we used the $prefix for caching the routes and giving to the route a new name ->name($prefix.'_home'); in this way I can cache all the route and I can call the routes using blade without prefix {{ route('name') }} but, needing the translated url of the actual page a made this on the top of the view:
#php
$ThisRoute = Route::currentRouteName();
$result = substr($ThisRoute, 0, 2);
if ($result =='it' ){
$routeName = str_replace('it_', '', $ThisRoute);
$url = route($routeName,[],true,'en');
} else {
$routeName = str_replace('en_', '', $ThisRoute);
$url = route($routeName,[],true,'it');
}
#endphp
Doing this I get the actual route name that should be it_home I check if start with it_ or en_, I remove the it_ or en_ prefix and I get the translated URL, now you can use the $url as <a href="{{ $url" }}>text</a> cause if I call the {{ route('page') }} I get the link, with the locale language.
This code is not very good, I know, but I written in 5 minutes, need more implementation, and check, but for the moment is just to play with Laravel.
It's a good way?? How can I do it better (except the blade link retrieving)?? Many solution I found used middleware, but I would like to avoid a link in the navbar like mysite.com/changelang?lang=en
Is a good approach overriding the app.locale_prefix?
First
according to your question, it's a bad practice to save the preferences into .env or session because as soon as the session is finished the saved language will be removed also it's common when you need to store any preferences related to your website such as (Color, Font, Language, ...etc) you must store any of them into the cache.
Second
honestly, your code is a very strange and NOT common way and there are two ways to handle what do you need
First
There is a very helpful and awesome package called mcamara it'll help you too much (I recommend this solution).
Second
you can do it from scratch using the lang folder located in the resource folder and you must create files with the same count of the needed languages then use the keys that you'll define into these files into views and you can prefix your routes with the selected language you can use group method like so
Route::group(['prefix' => 'selected_lang'], function() {
Route::get('first_route', [Controller::class, 'your_method']);
});
or you can add the selected language as a query string like so localhost:8000/your_route?lang=en you can follow this tutorial for more info.
I am trying to change words in string, I know laravel Str::replace() function but it converts if you write exact word. This is what i want to do :
$string = " this is #username and this is #username2"
I want to find usernames which starts with "#" and make them like below, i want to add <strong> html tag them :
$newstring = " this is <strong>#username</strong> and this is <strong>#username2</strong>"
I couldnt find the way to change dynamic value on str replace.
Thanks
Use preg_replace
$string = 'this is #username and this is #username2';
$newString = preg_replace('/(\#\w+)/', '<strong>$1</strong>', $string);
Docs: https://www.php.net/manual/en/function.preg-replace.php
I would like to create a slug that combines the title + a random string in Laravel.
I tried this, but nothing, in the second case it does nothing but combine the character string with the title.
Str::slug(request('title'), '-', Str::random());
or
Str::slug(request('title'), Str::random());
I would like something like this:
this-is-an-example-title-Jfij4jio4523q234
Double-check the method signature from https://laravel.com/docs/7.x/helpers#method-str-slug (and deeper at https://github.com/laravel/framework/blob/7.x/src/Illuminate/Support/Str.php#L552)
To be explicit, the second parameter of the method is the character used to replace whitespace, and the third parameter refers to the locale to use when generating the slug. That means you need your string to be fully composed before passing it to the method.
Assuming you want your slug joined by a - then something like this is what you want:
$value = request('title') . ' ' . Str::random();
$slug = Str::slug($value); // optionally Str::slug($value, '-'); to explicitly define the join
Str::Slug() has been defined as:
slug(string $title, string $separator = '-', string $language = 'en')
The third param can be seen as language with default value: en.
Str::slug($request->input('title').Str::random(40), '-');
I hope this helps.
I can't figure out how to search for text containing single quotes using XPATHs.
For example, I've added a quote to the title of this question. The following line
$x("//*[text()='XQuery looking for text with 'single' quote']")
Returns an empty array.
However, if I try the following
$x("//*[text()=\"XQuery looking for text with 'single' quote\"]")
It does return the link for the title of the page, but I would like to be able to accept both single and double quotes in there, so I can't just tailor it for the single/double quote.
You can try it in chrome's or firebug's console on this page.
Here's a hackaround (Thanks Dimitre Novatchev) that will allow me to search for any text in xpaths, whether it contains single or double quotes. Implemented in JS, but could be easily translated to other languages
function cleanStringForXpath(str) {
var parts = str.match(/[^'"]+|['"]/g);
parts = parts.map(function(part){
if (part === "'") {
return '"\'"'; // output "'"
}
if (part === '"') {
return "'\"'"; // output '"'
}
return "'" + part + "'";
});
return "concat(" + parts.join(",") + ")";
}
If I'm looking for I'm reading "Harry Potter" I could do the following
var xpathString = cleanStringForXpath( "I'm reading \"Harry Potter\"" );
$x("//*[text()="+ xpathString +"]");
// The xpath created becomes
// //*[text()=concat('I',"'",'m reading ','"','Harry Potter','"')]
Here's a (much shorter) Java version. It's exactly the same as JavaScript, if you remove type information. Thanks to https://stackoverflow.com/users/1850609/acdcjunior
String escapedText = "concat('"+originalText.replace("'", "', \"'\", '") + "', '')";!
In XPath 2.0 and XQuery 1.0, the delimiter of a string literal can be included in the string literal by doubling it:
let $a := "He said ""I won't"""
or
let $a := 'He said "I can''t"'
The convention is borrowed from SQL.
This is an example:
/*/*[contains(., "'") and contains(., '"') ]/text()
When this XPath expression is applied on the following XML document:
<text>
<t>I'm reading "Harry Potter"</t>
<t>I am reading "Harry Potter"</t>
<t>I am reading 'Harry Potter'</t>
</text>
the wanted, correct result (a single text node) is selected:
I'm reading "Harry Potter"
Here is verification using the XPath Visualizer (A free and open source tool I created 12 years ago, that has taught XPath the fun way to thousands of people):
Your problem may be that you are not able to specify this XPath expression as string in the programming language that you are using -- this isn't an XPath problem but a problem in your knowledge of your programming language.
Additionally, if you were using XQuery, instead of XPath, as the title says, you could also use the xml entities:
"" for double and ' for single quotes"
they also work within single quotes
You can do this using a regular expression. For example (as ES6 code):
export function escapeXPathString(str: string): string {
str = str.replace(/'/g, `', "'", '`);
return `concat('${str}', '')`;
}
This replaces all ' in the input string by ', "'", '.
The final , '' is important because concat('string') is an error.
Well I was in the same quest, and after a moment I found that's there is no support in xpath for this, quiet disappointing! But well we can always work around it!
I wanted something simple and straight froward. What I come with is to set your own replacement for the apostrophe, kind of unique code (something you will not encounter in your xml text) , I chose //apos// for example. now you put that in both your xml text and your xpath query . (in case of xml you didn't write always we can replace with replace function of any editor). And now how we do? we search normally with this, retrieve the result, and replace back the //apos// to '.
Bellow some samples from what I was doing: (replace_special_char_xpath() is what you need to make)
function repalce_special_char_xpath($str){
$str = str_replace("//apos//","'",$str);
/*add all replacement here */
return $str;
}
function xml_lang($xml_file,$category,$word,$language){ //path can be relative or absolute
$language = str_replace("-","_",$language);// to replace - with _ to be able to use "en-us", .....
$xml = simplexml_load_file($xml_file);
$xpath_result = $xml->xpath("${category}/def[en_us = '${word}']/${language}");
$result = $xpath_result[0][0];
return repalce_special_char_xpath($result);
}
the text in xml file:
<def>
<en_us>If you don//apos//t know which server, Click here for automatic connection</en_us> <fr_fr>Si vous ne savez pas quelle serveur, Cliquez ici pour une connexion automatique</fr_fr> <ar_sa>إذا لا تعرفوا أي سرفير, إضغطوا هنا من أجل إتصال تلقائي</ar_sa>
</def>
and the call in the php file (generated html):
<span><?php echo xml_lang_body("If you don//apos//t know which server, Click here for automatic connection")?>
i have no idea how wordpress use <!--more--> to seperate the post then create read more link.
any idea?
thanks
Use the word_limiter() function from the Text Helper included in CodeIgniter to shorted your post to a fixed number of words, then append the "read more" hyperlink to that text, and echo.
Text Helper Reference
take a look in the WP source, the function is located in wp-includes/post-template.php around line 200 in the get_the_content function
I wouldn't recommend just copying and pasting as it likely won't work, but you may get the logic behind it. WP uses a preg_match for the <!--more --> tag, then parses it if it exists..
$content = $pages[$page-1];
if ( preg_match('/<!--more(.*?)?-->/', $content, $matches) ) {
$content = explode($matches[0], $content, 2);
if ( !empty($matches[1]) && !empty($more_link_text) )
$more_link_text = strip_tags(wp_kses_no_null(trim($matches[1])));
$hasTeaser = true;
} else {
// so on