Is there anyway to highlight HTML embedded in PHP single and double quotes — which has no scope defined, within Textmate?
Example:
printf( 'This is some <strong>Text</strong>', 'foobar' );
Everything within the single quotes belong to the same scope. Its annoying. Has anyone tried to fix this somehow? I'd rather not alter the language files (without guidance), im not fluent in regex.
Nevermind, i found out how to do it. After reading on how scopes work in Textmate. I opened up the PHP languages panel under the Bundle Editor and pasted an include of the following scope name into the string-single-quoted scope:
text.html.basic
Heres the include:
{ include = 'text.html.basic'; },
and heres how the entire string-single-quoted section looks like now:
string-single-quoted = {
name = 'string.quoted.single.php';
contentName = 'meta.string-contents.quoted.single.php';
begin = "'";
end = "'";
beginCaptures = { 0 = { name = 'punctuation.definition.string.begin.php'; }; };
endCaptures = { 0 = { name = 'punctuation.definition.string.end.php'; }; };
patterns = (
{ include = 'text.html.basic'; },
{ name = 'constant.character.escape.php';
match = '\\[\\'']';
},
);
};
You would probably have to do some rather complicated editing of the scope definitions for HTML in order to get this to work as you describe. PHP files are HTML files by default in TextMate, so you're looking to define a scope where you have an HTML file with embedded PHP with strings that might be HTML. Not every string in PHP is going to be HTML, so you'd need to figure out a way to differentiate non-HTML strings from HTML strings, and if you're not fluent with regular expressions, it would probably take quite a bit of research and trial and error to get it right.
As an alternative, if you're actually using printf rather than simply using it as a generic example, consider using the function to format only what you need formatted and doing something like this.
<?php
$var = sprintf( '%d', $num );
?>
Here's the <strong><?php echo $var; ?></strong>.
Related
I am trying to loop through all the php files listed in an array called $articleContents and extract the variables $articleTitle and $heroImage from each.
So far I have the following code:
$articleContents = array("article1.php", "article2.php"); // array of all file names
$articleInfo = [];
$size = count($articleContents);
for ($x = 0; $x <= $size; $x++) {
ob_start();
if (require_once('../articles/'.$articleContents[$x])) {
ob_end_clean();
$entry = array($articleContents[$x],$articleTitle,$heroImage);
array_push($articlesInfo, $entry);
}
The problem is, the php files visited in the loop have html, and I can't keep it from executing. I would like to get variables from each of these files without executing the html inside each one.
Also, the variables $articleTitle and $heroImage also exist at the top of the php file I'm working in, so I need to make sure the script knows I'm calling the variables in the external file and not the current one.
If this is not possible, can you please recommend an alternative method?
Thanks!
Don't do this.
Your PHP scripts should be for your application, not for your data. For your data, if you want to keep it file-based, use a separate file.
There are plenty of formats to choose from. JSON is quite popular. You can use PHP's built-in serialization as well, which has support for more PHP-native types but is not as portable to other frameworks.
A little hacky but seems to works:
$result = eval(
'return (function() {?>' .
file_get_contents('your_article.php') .
'return [\'articleTitle\' => $articleTitle, \'heroImage\' => $heroImage];})();'
);
Where your_article.php is something like:
<?php
$articleTitle = 'hola';
$heroImage = 'como te va';
The values are returned in the $result array.
Explanation:
Build a string of php code where the code in your article scripts are wrapped inside a function that returns an array with the values you want.
function() {
//code of your article.php
return ['articleTitle' => $articleTitle, 'heroImage' => $heroImage];
}
Maybe you must do some adaptations to the strings due <?php ?> tags placements.
Anyway, this stuff is ugly. I'm very sure that it can be refactored in some way.
Your problem (probably) comes down to using parentheses with require. See the example and note here.
Instead, format your code like this
$articlesInfo = []; // watch your spelling here
foreach ($articleContents as $file) {
ob_start();
if (require '../articles/' . $file) { // note, no parentheses around the path
$articlesInfo[] = [
$file,
$articleTitle,
$heroImage
];
}
ob_end_clean();
}
Update: I've tested this and it works just fine.
So i have this code, $value2 is an array of values that I edit.
I have .txt document for each of the variable in the array.. for exemple
sometext_AA.txt
sometext_BB.txt
I currently have over 50 text files, and it make a BIG BIG BIG php files because i have the following code made for each of the files for exemple sometext_AA.txt...
I would like to make one script(the following) so that one script will work for all of my $value2(I do not delete the old texts files when the value are changed so i am unable to just make script to read all different text file, it has to be done that it read the active $value2 and process them...
I am not even sure if I am on the good way but i really hope someone can help me out.
Thank you!
$value2 = array("AA","BB","CC");
foreach($value2 as $value3) {
foreach($random1_' .$value3' as $random2_' .$value3') {
$random3_' .$value3' = 'sometext_.$value3'.txt;
$random4_' .$value3' = json_encode(file_get_contents($random3_' .$value3'));
echo $random4_' .$value3';
}
}
This is a exemple of current text i have in my file, I have a very big php file, and, id like a code to make it simple
foreach($random1_AA as $random2_AA) {
$random3_AA = 'sometext_AA.txt;
$random4_AA = json_encode(file_get_contents($random3_AA));
echo $random4_AA;
}
foreach($random1_BB as $random2_BB) {
$random3_BB = 'sometext_BB.txt;
$random4_BB = json_encode(file_get_contents($random3_BB));
echo $random4_BB;
}
foreach($random1_CC as $random2_CC) {
$random3_CC = 'sometext_CC.txt;
$random4_CC = json_encode(file_get_contents($random3_CC));
echo $random4_CC;
}
foreach($random1_DD as $random2_DD) {
$random3_DD = 'sometext_DD.txt;
$random4_DD = json_encode(file_get_contents($random3_DD));
echo $random4_DD;
}
I think that this is what you are looking for, using the $var_{$var_in_var} syntax that PHP allows (so you can include a variable in a variable name).
$value2 = array("AA","BB","CC");
foreach($value2 as $value3) {
foreach($random1_{$value3} as $random2_{$value3}) {
$random3_{$value3} = 'sometext_'.$value3.'.txt';
$random4_{$value3} = json_encode(file_get_contents($random3_{$value3}));
echo $random4_{$value3};
}
}
However, I stongly advise you to consider the following points in order to make your code maintainable:
Use appropriate variable names representing the real content of each variable (you shoud never use "value1", "value2", etc. as the name tells nothing about the variable content).
Don't use variables in variable names unless absolutely necessary, which is not your case. You can use arrays, which are better suited for doing that.
In fact, I don't even know what $random1_XX and $random2_XX are supposed to be. I don't see you defining them in the code sample you posted.
Here is an example of how clear and concise you code may be if you use my advice and if all you need to read all the files and print them in JSON format (which is the only thing the program sample you posted would be doing after corrections).
$file_codes = array('AA', 'BB', 'CC');
foreach($file_codes as $file_code) {
echo json_encode(file_get_contents('sometext_'.$file_code.'.txt'));
}
Of course, if you have anything else in your program (maybe some code using the variables $random3_XX and $random4_XX?), I cannot guess what it is so I can't really offer you help to optimize this code.
I apologize if this is something that has been discussed thoroughly here. I spent a good amount of time searching for an answer and can't seem to dig a definitive one up. Also, I'm pretty much an amateur when it comes to PHP.
I have an XML document that I'm trying to render as HTML using PHP. The XML is actually "theoretically" used for single-sourcing, meaning the hope is for using it as a source for producing both PDF and HTML output. So, the XML is actually made up of elements that serve as the parts of a manual. See below:
<topic>
<title>Some topic.</title>
<caution>
<para>Cautionary note 1.</para>
</caution>
<para>Paragraph 1</para>
<caution>
<para>Cautionary note 2.</para>
</caution>
<para>Paragraph 2</para>
<figure>
<graphic src="../some_path"/>
</figure>
</topic>
For PDF, I plan on writing an XSLT transform. For HTML, I have a script that successfully converts all the elements of the XML into HTML. The problem is, it seems to be converting the XML as parsed arrays. The above example renders with (using HTML equivalents):
All figure elements at the top.
All para elements in the middle (excluding para elements within the caution elements).
All caution elements at the bottom.
So, the document order is not preserved. Since this source is used to put together a manual, the document order is important.
My question: Is it possible to use PHP to parse XML into HTML and preserve document order? Again, I'm pretty much a PHP amateur so I apologize if my question seems obtuse. Any advice or pointers is welcome.
EDITED TO ADD SOME OF THE PHP
The PHP script is pretty lengthy so I will try to include as much of the relevant bits as possible.
In terms of the cautionary notes, the script initially defines a function:
//Display the cautions from the xml
function display_cautions($cautions)
{
foreach( $cautions as $caution )
{
foreach( $caution->para as $cautionpara )
{
printf("<p class='Text'>");
foreach( $cautionpara->{'attention-icon'} as $attentionicon )
{
printf("<img src='../../images/%s' width='25px' height='25px'>", htmlspecialchars($attentionicon['srcfile']));
}
$cautionpara = str_ireplace('<emph>', '<b>', $cautionpara);
$cautionpara = str_ireplace('</emph>', '</b>', $cautionpara);
printf("%s</p>", htmlspecialchars($cautionpara));
}
}
}
Then it constructs the document:
if (isset($_GET['ID']))
{
$introsections = $doc->{'intro-section'};
//printf("got here 1");
foreach( $introsections as $introsection )
{
//printf("got here 2");
$sectno = $introsection['sect-no'];
if ($sectno == $_GET['ID'])
{
$smtitle = $introsection->title->nodeValue;
$introgenerals = $introsection->{'intro-general'};
foreach( $introgenerals as $introgeneral )
{
//printf("got here 3");
$smtitle = $introgeneral->title;
$introid = $introgeneral['id'];
//Display the title
printf("<h2>%s</h2>", htmlspecialchars($smtitle));
//Match found
$topics = $introgeneral->topic;
foreach( $topics as $topic )
{
//Display the title
printf("<p class='Text12Bold'>%s</p>", htmlspecialchars($topic->title));
$topicparas = $topic->para;
//Get all the paragraphs
foreach( $topicparas as $topicpara )
{
//MH added: code to include xrefs here
//check for xrefs in this para
$xrefs = $topicpara->xref;
if (simple_xml_count($xrefs) > 0) {
//printf("<p class='Text'>%s</p>\n", htmlspecialchars($topicpara));
display_referral_links($xrefs, $topicpara);
} else {
$topicpara = str_ireplace('<emph>', '<b>', $topicpara);
$topicpara = str_ireplace('</emph>', '</b>', $topicpara);
?>
<p class='Text'><?php printf($topicpara) ?></p>
<?php
}
}
Then it calls the caution function:
//Get all the cautions with images where applicable
display_cautions($topic->caution);
In between the document construction and the function call, it constructs tables, subtopics and figures. Similar functions are in place for warnings, notes, and lists.
I am designing a Mail Template editor in my application. I need an idea to find the occurance of specific variables to be able to convert them using preg_replace or preg_match in my code.
For example, my template looks like this: (Sample only) this is what is returned from the textarea variable.
<p>Thank you for your order at {site_name}.</p>
In this example, I would like to replace the {site_url} with a specific variable or code from PHP since I can't parse PHP directly into the textarea.
Hope my question was clear, any help appreciated.
Edit: Is my question clear? I need to replace the {} strings using my own php code. The php code cann't be used in textarea directly. That is why i need to find a templating system that replace predefined variables {... } but convert them using php when interpreting the template.
Do you mean something like this?
<p>Thank you for your order at <?=$site_name?>.</p>
or
<p>Thank you for your order at <?php echo $site_name?>.</p>
edited:
Ahhh, do you mean something like this then:
$html = '<p>Thank you for your order at {site_name}.</p>';
$php_variables_array = array(
"site_url" => "http://www.google.co.uk",
"site_name" => "Google",
);
foreach ($php_variables_array as $key => $value)
{
$html = str_replace("{" . $key . "}", $value, $html);
}
echo $html;
<?php echo $site_name;?>
I am developing a php website that needs to be multilingual.
For this reason, I implemented a translation function which has the following header:
function t($string, $replace_pairs = array(), $language = NULL)
Basically, this function is called like this in multiples files of my project:
echo '<p>' . t('Hello world!') . '</p>';
$hello_String = t("Hello #name!", array('#name'=>$username));
I haven't generated the translation strings yet and I would like to generate multiple translation file automatically (one for each language).
What I am looking for is a bash program (or a single command, using grep for example) that would look for every call to this t() function and generate a php file with the following structure:
<?php
/* Translation file "fr.php" */
$strings['fr']['Hello world!'] = '';
$strings['fr']['Hello #name!'] = '';
Has anyone ever encountered this situation and could help me with this ?
Thank you very much.
Kind regards,
Matthieu
Yes, you're not exactly the first to come across this. :)
You can use the venerable gettext system for this, you don't need to invent your own functions. Then you'd get to use xgettext, which is a command line utility to extract strings using the _() function.
If you want to roll your own system for whatever reason, your best bet is to write a PHP script which uses token_get_all to tokenize the source, then go through the tokens and look for T_FUNCTIONs with the value t.
No need to reinvent the wheel
Drupal uses the same t() function for its localization and the potx module is your friend.
If you don't already have, or want to install, a drupal instance you can look at the potx.inc file and reuse it in your script.
Here is the complete API documentation for the translation template extractor.
Try this script http://pastie.org/4568713
Usage:
php script.php ./proj-directory lang1 lang2 lang3
This creates lang1.php, lang2.php, lang3.php files in ./lang directory
You need two functions:
1- scan directories for php files. like this
2- match your t function, grep string and generate the language file. like
function genLang($file) {
$content = file_get_contents($file);
preg_match(...);
foreach(...){
echo(...);
}
}
Yii framework also uses same functionality,
see their MessageCommand class
https://github.com/yiisoft/yii/blob/master/framework/cli/commands/MessageCommand.php#L125
What you need is a (very simple) "template system", but there are two instances of templating in your problem.
Transform "Hello $X!" into "Hello Jonh!" or "Hello Maria!", setting $X. (PHP do this for you in string declarations).
Select the adequate template: "Hello $X!" for english, "¡Hola $X!" for spanish.
The item 1 is the more simple, but the algorithm order is 2,1 (item 2 them item 1).
For this simple task you not need a regular expression (to reinvent the "string with place-holder" of PHP).
Illustrating
For item 1, the simplest way is to declare a specialized function to say "Hello",
// for any PHP version.
function template1($name) { return "<p>Hello $name!</p>";}
print template1("Maria");
For item 2 you need a generalization, that PHP do also for you, by a closure,
header('Content-Type: text/html; charset=utf-8'); // only for remember UTF8.
// for PHP 5.3+. Use
function generalTemplate1($K) {
// $K was a literal constant, now is a customized content.
return function($name) use ($K) {return "<p>$K $name!</p>"; };
}
// Configuring template1 (T1) for each language:
$T1_en = generalTemplate1('Hello'); // english template
$T1_es = generalTemplate1('¡Hola'); // spanish template
// using the T1 multilingual
print $T1_en('Jonh'); // Hello Jonh!
print $T1_es('Maria'); // ¡Hola Maria!
For more templates, use generalTemplate2(), generalTemplate3(), etc.; $T2_en, $T2_es, $T2_fr, $T3_en, $T3_es, etc.
Solution
Now, for pratical use, you like to use arrays... Well, there are a datastructure problem,
and more 1 level of generalization. The cost is variable-name parser for place-holders. I used simple regular expression with preg_replace_callback().
function expandMultilangTemplate($T,$K,$lang,$X) {
// string $T is a template, a HTML structure with $K and $X placeholders.
// array $K is a specific language constants for the template.
// array $lang is the language, a standard 2-letter code. "en", "fr", etc.
// array $X is a set of name-value (compatible with $T placeholders).
// Parsing steps:
$T = str_replace('{#K}',$K[$lang],$T); // STEP-1: expand K into T with lang.
// STEP-2: expand X into T
global $_expMultTpl_X; // need to be global for old PHP versions
$_expMultTpl_X = $X;
$T = preg_replace_callback(
'/#([a-z]+)/',
create_function(
'$m',
'global $_expMultTpl_X;
return array_key_exists($m[1],$_expMultTpl_X)?
$_expMultTpl_X[$m[1]]:
"";
'
),
$T
);
return $T;
}
// CONFIGURING YOUR TEMPLATE AND LANGUAGES:
$T = "<p>{#K} #name#surname!</p>";
$K = array('en'=>'Hello','es'=>'¡Hola');
// take care with things like "!", that is generic, and "¡" that is not.
// USING!
print expandMultilangTemplate(
$T, $K, 'en', array('name'=>'Jonh', 'surname'=>' Smith') );
print expandMultilangTemplate($T, $K, 'es', array('name'=>'Maria'));
I tested this script with PHP5, but it runs with older (PHP 4.0.7+).
About "multilingual files": if your translations are into files, you can use somthing like
$K = getTranslation('translationFile.txt');
function getTranslation($file,$sep='|') {
$K = array();
foreach (file($file) as $line) {
list($lang,$words) = explode($sep,$line);
$K[$lang]=$words;
}
}
and a file as
en|Hello
es|¡Hola
Simplest with PHP 5.3
If you using PHP 5.3+, there are a simple and elegant way to express this "simplest multilingual template system",
function expandMultilangTemplate($T,$K,$lang,$X) {
$T = str_replace('{#K}',$K[$lang],$T);
$T = preg_replace_callback(
'/#([a-z]+)/',
function($m,$X=NULL) use ($X) {
return array_key_exists($m[1],$X)? $X[$m[1]]: '';
},
$T
);
return $T;
}