I have this string
string(2091) "
"roots" => array(
array(
"driver" => "LocalFileSystem", // driver for accessing file system (REQUIRED)
"path" => "../files/", // path to files (REQUIRED)
//"URL" => dirname($_SERVER["PHP_SELF"]) . "/../files/", // URL to files (REQUIRED)
"accessControl" => "access" , // disable and hide dot starting files (OPTIONAL)
"alias" => "Root",
//"uploadDeny" => array("all"),
"attributes" => array(
array(
"pattern" => "/\manuali$/", //You can also set permissions for file types by adding, for example, <b>.jpg</b> inside pattern.
// "pattern" =>"/\PROVA$/",
"read" => true,
"write" => false,
"locked" => true,
),
array(
"pattern" => "/rapporti$/", //You can also set permissions for file types by adding, for example, <b>.jpg</b> inside pattern.
// "pattern" =>"/\PROVA$/",
"read" => true,
"write" => true,
"locked" => true,
)
[...]
";
i want to put into array the entire value of a string. Ex:
array(
"roots" => array(
array(
"driver" => "LocalFileSystem", // driver for accessing file system (REQUIRED)
"path" => "../files/", // path to files (REQUIRED)
//"URL" => dirname($_SERVER["PHP_SELF"]) . "/../files/", // URL to files (REQUIRED)
"accessControl" => "access" , // disable and hide dot starting files (OPTIONAL)
"alias" => "Root",
//"uploadDeny" => array("all"),
"attributes" => array(
array(
"pattern" => "/\manuali$/", //You can also set permissions for file types by adding, for example, <b>.jpg</b> inside pattern.
// "pattern" =>"/\PROVA$/",
"read" => true,
"write" => false,
"locked" => true,
),
array(
"pattern" => "/rapporti$/", //You can also set permissions for file types by adding, for example, <b>.jpg</b> inside pattern.
// "pattern" =>"/\PROVA$/",
"read" => true,
"write" => true,
"locked" => true,
)
[...]
);
i have tried str_split() implode() array_push()... but every function put the string into array in this mode array(string(" "))i want to put in this mode array(" ").
Thanks
If your string is parseable and you don't mind about possible injections, you can simply eval your array representation.
For example, if your string is in $arrayStr and you want to create an array $myArray from that:
$arrayStr = '"roots" => array ( ... )';
eval('$myArray = array(' . $arrayStr . ');');
Note that if $arrayStr is not entirely controller by you from generation to conversion, it is highly risky since anything in it would be evaluated.
A better solution to exchange a whole array between parts of your application would be to serialize() it beforehand to create a string representation of your array/object which can be stored, and then unserialize it when you need it in its original form.
There's two main methods I can think of.
One, is to use some sort of complex pattern matching loop using preg_match. You can split the string into each line by using explode and \n to convert it into an array (of each line), loop through each row, and use pattern matching (regex) to figure out what to do with it.
The second method is incredibly dangerous, so I highly advise you to not use it, but php has it's own eval function which would let PHP interpret the string as actual PHP.
You would need to append a variable assignment inside the string e.g.
$arrayString = "$var = array(' . $arrayString . ');";
And then
eval($arrayString);
However, you really don't want to be doing this if you can. From the PHP docs:
Caution
The eval() language construct is very dangerous because it allows
execution of arbitrary PHP code. Its use thus is discouraged. If you
have carefully verified that there is no other option than to use this
construct, pay special attention not to pass any user provided data
into it without properly validating it beforehand.
Related
I have an associate array inside a PHP class method going like this:
// ...
$filters = [
self::FILTER_CREATION_DATE => "Base/*/Creation/Date.php",
self::FILTER_CREATION_DATE_BETWEEN => "Base/*/Creation/Date.php",
self::FILTER_CREATION_DATE_GREATER => "Base/*/Creation/Date.php",
self::FILTER_CREATION_DATE_GREATER_OR_EQUAL => "Base/*/Creation/Date.php",
self::FILTER_CREATION_DATE_LESS => "Base/*/Creation/Date.php",
self::FILTER_CREATION_DATE_LESS_OR_EQUAL => "Base/*/Creation/Date.php",
];
// ...
What I would like to do is to convert this string from:
self::FILTER_CREATION_DATE_BETWEEN => "Base/*/Creation/Date.php",
to this one:
self::FILTER_CREATION_DATE_BETWEEN => "Base/*/Creation/Date/Between.php",
I would like to use a RegEx to extend the string but leave the rest untouched. I need to do this because there's more than 120 constants defined ending with *_BETWEEN.
How can I do this?
In the Intellij editor or the free Notepad++, you can find and replace by regex.
I'm sure other IDE's have similar functionality
Find self::([_A-Z]+)_BETWEEN => "(.*)/Date.php"(,)*
Replace self::$1_BETWEEN => "$2/Date/Between.php"$3
The regex groups the variable components of your search together by wrapping it in ()
In the replace you can reference them in order by $1, $2, etc..
I'm trying to write some code that will generate a php file with an array, like this.
However, in order to create a correct configuration file I need to be able to leave expressions 'as is' within the array. This is because the file will be used by many users and the expressions evaluate based on environmental variables, etc. the user has set up.
So, say we have this key/value in the array I eventually want to output to the file:
[
...
'connection' => $isFork ? $sourceArray['connection'] : config('database.default'),
...
]
When this array is eventually written out to a php file (right now using var_export and file_put_contents) I will see
'connection' => config('database.default')
become
'connection' => 'default_connection',
because the expression is evaluated. What I need is a way to prevent expressions as values in the array from being evaluated but also ensuring
'connection' => $isFork ? $sourceArray['connection']
does evaluate to
'connection' => 'my_connection'
Is there any way to do this?
EDIT: I basically want to do this but in reverse and with expressions.
If I understand you correctly, your solution is to have a string representation of your array so the statements are not evaluated. I would serialize that array and put that string into the file. Tell your peeps to unserialize it right after they receive it. Better yet, json_encode your array which is going to give you a json string. You can put that in via put_file_contents and tell your peeps to json_decode the contents. They can use it as such json_decode($content, TRUE) which will give them back the associative array.
Update
So you want to write straight up PHP. I see that you have connection stuff in your array so I am thinking it is safe to think it is some sort of a configuration file that includes connection settings etc.
// filename should have the .ini at the end
function writeConfig( $filename, $yourArray ) {
$fh = fopen($filename, "w");
// making sure its available
if (!is_resource($fh)) {
return false;
}
// start dumping you array to the file
foreach ($yourArray as $key => $value) {
fwrite($fh, sprintf("%s = %s\n", $key, $value));
}
fclose($fh); // close file
return true;
}
when you want to read it
function readConfigFile( $fileThatMadeAbove ) {
return parse_ini_file($fileThatYouMadeAbove, false, INI_SCANNER_NORMAL);
}
Since it is config info, it may be better to use the ini in php.
If you want to try plain simple solution
$fp=fopen('filename.php','w');
fwrite($fp, "$yourArray");
fclose($fp);
I honestly do not know if you can do "$yourArray" or not and I do not have a place to test it. You most likely need to do a print_r($yourArray) because it is a string that you write to a file which is why I made my recommendation above.
I am out of ideas. Good luck (:
This isn't possible using var_export. The best way I can see to do this is to create a string of the output and use file_put_contents to output this to a file.
This could be achieved by replicating the array structure, e.g.
$arr_str = "[\n";
. "\t'simple_annotations' => false,\n"
. "];";
Or by creating a helper function to use instead of var_export. Something like this:
function var_str($var, $level = 0){
if(is_array($var)) return arr_str($var, $level+1);
elseif(is_string($var)) return '\''.$var.'\'';
elseif(is_numeric($var)) return $var;
elseif(is_null($var)) return 'null';
elseif(is_bool($var)) return ($var ? 'true' : 'false');
}
function arr_str($arr, $level){
$str = "[\n";
foreach($arr as $k => $e){
$str .= str_repeat("\t", $level);
$str .= "'".$k."' => ".var_str($e, $level).",\n";
}
return $str.str_repeat("\t", $level-1).']';
}
print var_str($my_array);
After searching for a few hours I came to the conclusion the only way to take full control over what I wanted to do was to use a templating engine.
The project this is for uses Laravel so I used Blade but any engine would work (I initially tried this with Twig).
I wrote out each section of my config as if it was a regular php array and then used Blade bracketing to encompass the logic needed to find the right value for each key. If the value was not an expression I evaluated the code, and if it was I wrote the expression into a string.
I ended up with this:
//example.blade.php
[
'meta' => '{{{ $isFork ? $data['metadata']['driver'] : 'annotations' }}}',
'connection' => {{{ $isFork ? '\''.$data['connection'].'\'' : 'config("database.default")' }}},
'paths' => {{ var_export(ArrayUtil::get($data['metadata']['paths'], $data['metadata']), true) }},
'repository' => '{{{ ArrayUtil::get($data['repository'], EntityRepository::class) }}}',
'proxies' => [
'namespace' => {{{ isset($data['proxy']['namespace']) ? '\'' . $data['proxy']['namespace'] .'\'' : 'false' }}},
'path' => '{{{ ArrayUtil::get($data['proxy']['directory'], storage_path('proxies')) }}}',
'auto_generate' => {{{ ArrayUtil::get($data['proxy']['auto_generate'], env('DOCTRINE_PROXY_AUTOGENERATE', 'false')) }}}
],
'events' => [
'listeners' => [],
'subscribers' => []
],
'filters' => []
]
and the output:
[
'meta' => 'yaml',
'connection' => config('database.default'),
'paths' => array(
0 => '/proj/app/Models/mappings',
),
'repository' => 'Doctrine\ORM\EntityRepository',
'proxies' => [
'namespace' => false,
'path' => '/proj/storage/proxies',
'auto_generate' => false
],
'events' => [
'listeners' => [],
'subscribers' => []
],
'filters' => []
]
You can see that where I potentially needed to expand an array I used var_export. Other than it was pretty straight forward.
I have a document with a tag '*'
Yet when I construct a term query it returns no results. How can I query documents with the tag '*'. My guess is it's a special character that needs to be escaped.
Update with answer
I needed to set the property to not analyzed so that elastic search wouldn't strip out punctuation etc.
$myTypeMapping = array(
'_source' => array(
'enabled' => true
),
'properties' => array(
'tag' => array("type" => "string", "index" => "not_analyzed")
)
);
$indexParams['body']['mappings']['file'] = $myTypeMapping;
If your tag field is analyzed then the the star is not indexed. See for yourself:
curl -XGET 'localhost:9200/_analyze?analyzer=standard' -d '*'
Response:
{"tokens":[]}
You will need to change the field to not_analyzed or to change the analyzer.
I'm trying to parse some input using regex. The input will be in the format:
{somevalue:3}
The aim is to display 'som' (no quotemarks).
At the moment, I have:
'echo' => array(
'search' => '~\{((?:'.$this->preg['var'].')(?:\.)?)\}~sU',
'replace' => "'.\$this->_get('\\1').'"
)
Which works great with my template system, to echo the standard variable (i.e. 'somevalue'). However, I wish to allow the user to use the : delimiter to limit the number of characters to output (i.e. {somevalue:3} would display 'som').
I tried:
'echo' => array(
'search' => '~\{((?:'.$this->preg['var'].')(?:\.)?:(.*)/)\}~sU',
'replace' => "'.substr(\$this->_get('\\1'),0,\\2).'"
)
But this didn't work. I don't really understand regex to be honest so any help would be much appreciated.
It looks like you have an extra '/' in the new search expression.
|
v
'search' => '~\{((?:'.$this->preg['var'].')(?:\.)?:(.*)/)\}~sU',
I'm not familiar with the templating system you're using, but it appears that the replace expression would need to be changed as well.
'replace' => "'.substr(\$this->_get('\\1'),0,\$this->_get('\\2')).'"
Put these together and you'd get something like this to try:
'echo' => array(
'search' => '~\{((?:'.$this->preg['var'].')(?:\.)?:(.*))\}~sU',
'replace' => "'.substr(\$this->_get('\\1'),0,\$this->_get('\\2')).'"
)
It should be noted that if this works, the old way of doing input won't work anymore. In other words, you'll always have to use the format {<string>:<num_of_chars>} and not just {<string>}.
$s = preg_replace_callback(
'/\{([^:]+):(\d+)\}/',
create_function('$m', 'return substr($m[1], 0, $m[2]);'), $s);
Test this code here.
Let's say i have an array.
$less_user_variables = array(
"bodyBackground" => array(
"value" => "#ffffff",
"description" => __( "Body background", AI1EC_PLUGIN_NAME ),
"tab" => "general",
"type" => "color",
),
i need to i18n the description. So i wrap it into a __() call. So when i create the .pot file "Body Background" is included. Now let's say i save the array to the db and later on retrieve it
$less_variables = get_option('less_variables');
can i use _() again on the description to tranlsate it?I think that at runtime all that _() does is actually check for a translation of the variable that it gets and for this reason
$description = __($less_variables["bodyBackground"]["description"], AI1EC_PLUGIN_NAME );
Should give me the translation of "Body Background", am i right?The rule that __() can't be used with variables is just for creating the .pot files but at runtime it would work with a variable, am i right?
Or should i use each and every time the $less_user_variables original array?
One more thing that ( i think ) supports my thoughts is that
function __( $text, $domain = 'default' ) {
return translate( $text, $domain );
}
so if i pass a variable or a string, actually nothing changes. Am i correct?
actually in your example, the $less_user_variables['bodyBackground']['description'] variable contains the translated text. So when you save the array, you actually save the translated value, so for accessing translated text, you just need to check $less_variables['bodyBackground']['description']
__() function is very simple as you can see - you put there string and recieve translated string
In this case I would do this (after pot file generation) :
$less_user_variables = array(
"bodyBackground" => array(
"value" => "#ffffff",
"_description" => 'Body background',
"tab" => "general",
"type" => "color",
),
Just to be sure that _description contains the good string.
And after :
$less_variables = get_option('less_variables');
$less_variables['bodyBackground']['description'] = __($less_variables['bodyBackground']['_description'], AI1EC_PLUGIN_NAME);