preg_replace capture group check - php

I'm trying to add a new bbcode to my phpfusion application. Im using with preg_replace. Here's the code:
$text = preg_replace(
"#\[gameimg( float:(left|center|right))?\]((http|ftp|https|ftps)://)(.*?)(\.(jpg|jpeg|gif|png|JPG|JPEG|GIF|PNG))\[/gameimg\]#sie",
"'<span style=\"display: block; max-width: 350px; margin: 0 0 5px 5px; $1\"><img src=\"'
. (strlen('$3') > 0 ? '$3' : BASEDIR.GAMESDIR)
. '$5$6\" alt=\"$5$6\" style=\"border:0px; max-width: 350px;\" /></span>'",
$text
);
If I supply an absolute url (for ex. [gameimg]http://localhost/dirname/file.jpg[/gameimg]) everything works fine, the picture shows up as expected. But if i omit the protokol and hostname using relative url ([gameimg]dirname/file.jpg[/gameimg]) i expect to append the basedir.gamedir constant to the given url but it doesn't work at all, it prints out the original bbcode without any replacement, not the image. What am i doing wrong?

A couple things here:
That is a giant preg_replace call. Maybe you could break this problem into smaller parts so that it is easier to understand/maintain?
You are using the "ignore case" modifier (i), yet you have things like (jpg|JPG). This is redundant.
Your question asks why [gameimg] tags without http://.. don't get matched. Well this is because of the required ((http|ftp|https|ftps)://) in your regex. You should make this section optional by adding a ?, like this:
((http|ftp|https|ftps)://)?

Related

Laravel description formatting

I have a table of items which has description field. When listing out all items I would like to show exactly three rows of text followed by "..." if the text is longer.
I can do something like
<style>
.box {
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
-ms-text-overflow: ellipsis;
height: 60px;
}
</style>
...which works fine when there is a lot of text and the text is split in several lines. But if I have no new line chars in text I see only one line of text which is shortened.
Also if I have text formated like
Something
//blank-line
//blank-line
I am writing about something, because something is not nothing
I get my three lines...but it looks bad because first line is only "Something", and the two other are blank. So I figured I'd have to pre-format it before I send it from controller to view, and I tried first to approach that problem by removing empty lines and connecting whole text to one line, however this does nothing
$description = preg_replace( "/\r|\n/", "", $array[0]->description);
return $description
Which is maybe excepted since HTML formatted text enters the database
<p class="MsoNormal">Something<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Blah blah...something else...
Does anyone have an idea how to solve this?
Naturally, text will flow to the next line when it reaches the edge of its container element in the browser. I assume your container's width is controlled by some styling (whether fixed or responsive).
So in your case I'd ditch the ellipsis styling, see (from physically looking in the browser) how many characters it takes to produce the 3 lines you desire, and then do (I also assume you don't want to keep the HTML):
$description = strip_tags($array[0]->description);
if (strlen($description) > $maximumLength) {
$description = substr($description, 0, $maximumLength) . "...";
}
return $description
Of course there are other ways to do it on the client side with CSS or JavaScript, but what I see on most sites is they settle on a fixed length for their excerpt and just say any text longer than x characters must be truncated.

PHP: How can you remove/replace a specific href attribute value

I am parsing some articles from a database with php and in the articles there are links which I would like to overwrite. Link always start with "http://cdn.example.com/" and the end parser is htmlspecialchars_decode($item->parse_articles(), ENT_NOQUOTES).
So before the articles are passed to the HTML DOM, I would like to replace all those href's that contain (?) example.com or maybe even if faster and possible to remove the <a> completely.
.
How is this possible? and if possible, is this considered faster option than passing it first to the DOM and manipulating it from there on the client-side?
You could try something like the following in PHP:
$newtext = preg_replace('/^("http:\/\/cdn\.example\.com\/){1}(.*)("){1}$/', '"#" class="disabled-link"', $oldtext);
$oldtext being your input article as a string.
$newtext being the text to echo on the page.
Broken down:
Find text starting with "http://cdn.example.com/
Then match anything
Stop at "
Replace with "#" class="disabled-link"
This should let you remove the link and also I added the class part so that you can add some CSS to style the links as text.
Example:
.disabled-link{
color:#000;
pointer-events: none;
cursor: default;
text-decoration: none;
}
All this combined will provide users with a link that is completely invisible without looking into the DOM or the source.

Remove whitespace/new lines/comments. Regex?

I'm currently making sort of a CSS minifier and well, I think examples for what I'm trying to achieve are the simplest way to explain.
I'm trying to transform this:
/* CSS Content */
.class{
text-align:center;
border-bottom:1px solid #ccc;
}
.anotherclass, .another, .another{
text-align:center;
border-bottom:1px solid #ccc;
}
Into:
.class{text-align:center;border-bottom:1px solid #ccc;}.anotherclass,.another,.another{text-align:center;border-bottom:1px solid #ccc;}
Thus: removing comments, unnecessary whitespace and new lines.
So far I got to remove the comments and new lines (Using one expression and a function exploding the string on \n, then appending the parts). The whitespaces are a bit more difficult, since the whitespaces within the {} should be removed but not between the colon and semicolon.
Since I'm quite inexperienced with the use of regular expressions, have no good reference book at hand and Google does'nt seem to have the answer: I'm wondering if anyone here can help me with creating one good Regex to accomplish this.
Thanks in advance!
If you must do it this way then this will minify the example you gave:
(/\*[^/]+\*/|^\t*|^\s*|\n|\s+(?=[\{.])|(?<=[\{;])\s+)
It assumes the flavour of regex you're using allows positive look-behinds
I guess you could try something like this:
(?<=[{};])\s+|\/\*.+?\*\/
http://rubular.com/r/djDtEPzEV0
Cleans out whitespace in front of parentheses, semicolons and all comments.

Using functions inside preg_replace

$TOPIC_CONTENT = preg_replace("!<code>(.+)</code>!is","<div style='color: #00FF00;
background-color: #000000; border-radius: 5px; margin: 5px;"<pre>".htmlspecialchars("$0")."</pre></div>",$TOPIC_INFO->content);
How can I get this to work? I have no idea how to pull this off, and I know my current way is invalid.
Use preg_replace_callback. Be a little careful with your regex .. I think you want to use .+? instead of just .+. The usual mantra is "don't parse html with regex," but for something as simple as this I don't see the harm.
Except for preg_replace_callback as in tandu's answer, you can also use the /e switch, and your replacement string will be *e*valuated as PHP code, and its result will be used.
I.e you could do:
preg_replace("!<code>(.+?)</code>!ise",
'"<pre style=\"color: #0f0; background: #000;\">" . htmlspecialchars("$1") . "</pre>"',
$string);

Regex and PHP: adding ellipsis after X number of chars

Should be fairly simple for someone who knows regex. I am unfortunately not among those in the know.
How can one append ellipsis to anything over 27 chars in the below example, so that the fourth link listed will appear as http://iamanextremely.com/long/lin?
<?php
$input = <<<EOF
http://www.example.com/
http://example.com
www.example.com
http://iamanextremely.com/long/link/so/I/will/be/trimmed/down/a/bit/so/i/dont/mess/up/text/wrapping.html
EOF;
$output = preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,27})[^(\s|,)<]*)/",
'http://$2$4', $input);
You could use preg_replace_callback to apply a callback to all matched urls. In the callback you can make stuff as fancy as you wish.
$output = preg_replace_callback('#(http://|www\\.)[^\\s<]+[^\\s<,.]#i',
'trimlong',$input);
function trimlong($match)
{
$url = $match[0];
$disp = $url;
if ( strlen($disp) > 24 ) $disp = substr($disp,0,24)."...";
return "$disp";
}
(ps. I just took your regexp to start with, I don't think matching a url should be that cumbersome.)
Unless you need to match a specific format, i.e. only the http:// links, a regex is overkill. Just use string functions and loop over your urls testing their length. If you want to get fancy, use explode() and array_walk()
if (strlen($url) > 27) {
echo substr($url, 0, 27) . '...';
}
else {
echo $url;
}
If this is for display in an HTML page, you might consider using CSS to style it with an ellipsis rather than manually truncating it.
You would use CSS something like this:
.cutshort {
overflow: hidden;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
white-space: nowrap;
width:100%;
}
The text would then be truncated on screen and be given an ellipsis, even though the HTML code contained the full string.
This technique is not suited to all cases, but where it works it is an excellent alternative to hacking around with your content before sending it to the user.
One important note: The current version of Firefox browser doesn't display the ellipsis dots. It does still truncate correctly though, so it's not a disaster. All other browsers do show the dots, and hopefully a new version of firefox due soon will add it too.

Categories