get byte value from shorthand byte notation in php.ini - byte

Is there any way to get the byte values from the strings returned from functions like ini_get('upload_max_filesize') and ini_get('post_max_size') when they are using shorthand byte notation? For example get 4194304 from 4M ? I could hack together a function that does this but I would be surprised if there wasn't some built in way of doing this.

The paragraph you linked to ends:
You may not use these shorthand notations outside of php.ini, instead
use an integer value of bytes. See the ini_get() documentation for an
example on how to convert these values.
This leads you to something like this (which I have slightly modified):
function return_bytes($val)
{
$val = trim($val);
if (is_numeric($val))
return $val;
$last = strtolower($val[strlen($val)-1]);
$val = substr($val, 0, -1); // necessary since PHP 7.1; otherwise optional
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
Use it like so:
echo return_bytes("3M");
// Output: 3145728
There is no built-in function to perform this task; recall that, really, INI settings are designed for use internally within PHP. The PHP source uses a similar function to the above.

Gah! Just found the answer on http://www.php.net/manual/en/function.ini-get.php
Just needed to RTM...
function return_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}

This is my suggestion which should be future-proof (with regard to PHP Versions 7++)!
function return_bytes($val, $gotISO = false) {
// This is my ultimate "return_bytes" function!
// Converts (not only) the PHP shorthand notation which is returned by e.g. "ini_get()"
// Special features:
// Doesn't need regular expression and switch-case conditionals.
// Identifies beside "Kilo", "Mega" and "Giga" also "Tera", "Peta", "Exa", "Zetta", and "Yotta" too!
// Ignores spaces and doesn't make no difference between e.g. "M" or "MB"!
// By default possible commas (,) as thousand separator will be erased. Example: "1,000.00" will "be 1000.00".
// If ($gotISO == true) it converts ISO formatted values like "1.000,00" into "1000.00".
$pwr = 0;
if(empty($val)) return 0;
$val = trim($val);
if (is_numeric($val)) return $val;
if ($gotISO) {
$val = str_replace('.','',$val); // wipe possibe thousend separators (.)
$val = str_replace(',','.',$val); // convert ISO comma to value point
} else {
$val = str_replace(',','',$val); // wipe possibe thousend separators (,)
}
$val = str_replace(' ','',$val);
if (floatval($val) == 0) return 0;
if (stripos($val, 'k') !== false) $pwr = 1;
elseif (stripos($val, 'm') !== false) $pwr = 2;
elseif (stripos($val, 'g') !== false) $pwr = 3;
elseif (stripos($val, 't') !== false) $pwr = 4;
elseif (stripos($val, 'p') !== false) $pwr = 5;
elseif (stripos($val, 'e') !== false) $pwr = 6;
elseif (stripos($val, 'z') !== false) $pwr = 7;
elseif (stripos($val, 'y') !== false) $pwr = 8;
$val *= pow(1024, $pwr);
return $val;
}
... have fun with it!

I found a lot of solution to solve this problem and there should have been a builtin function to solve this. In any case two things to highlight about this problem:
This is very specific to PHP's shorthand byte values as explained here: http://php.net/manual/en/faq.using.php#faq.using.shorthandbytes and should only be used in this context.
Most modern IDEs will give warning for switch statements without break.
Here is a solution that covers everything:
/**
* Convert PHP's directive values to bytes (including the shorthand syntax).
*
* #param string $directive The PHP directive from which to get the value from.
*
* #return false|int Returns the value of the directive in bytes if available, otherwise false.
*/
function php_directive_value_to_bytes($directive) {
$value = ini_get($directive);
// Value must be a string.
if (!is_string($value)) {
return false;
}
preg_match('/^(?<value>\d+)(?<option>[K|M|G]*)$/i', $value, $matches);
$value = (int) $matches['value'];
$option = strtoupper($matches['option']);
if ($option) {
if ($option === 'K') {
$value *= 1024;
} elseif ($option === 'M') {
$value *= 1024 * 1024;
} elseif ($option === 'G') {
$value *= 1024 * 1024 * 1024;
}
}
return $value;
}

Neither one of the Version shown above will work with PHP 7.2x anymore, as I found out.By use of this,with PHP 7.0 + 7.1, it works, but not with PHP 7.x
Ernie
private function return_bytes ($val) {
if(empty($val))return 0;
$val = trim($val);
preg_match('#([0-9]+)[\s]*([a-z]+)#i', $val, $matches);
$last = '';
if(isset($matches[2])){
$last = $matches[2];
}
if(isset($matches[1])){
$val = (int) $matches[1];
}
switch (strtolower($last)){
case 'g':
case 'gb':
$val *= 1024;
case 'm':
case 'mb':
$val *= 1024;
case 'k':
case 'kb':
$val *= 1024;
}
return (int) $val;
}

Here is one way.
$str=ini_get('upload_max_filesize');
preg_match('/[0-9]+/', $str, $match);
echo ($match[0] * 1024 * 1024); // <--This is MB converted to bytes

Related

How to add another array value in codeigniter using getRecords

The orignial code was like this , I want to get landline_no value also in getRecords, How to do that
public function checklead() {
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead));
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead));
if($lead->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';}
What I have achieved so far,but not getting array values from getRecords
$lead = $_POST['number'];
$check = $this->common_model->getRecords('leads',array("phone_no"=>$lead),array("landline_no"=>$lead));
//echo "<pre>";
//print_r($check);
//echo $check[0]['landline_no'];exit;
if(count($check) > 0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$lead,"landline_no"=>$check[0]['landline_no']));
Code for getRecords:
function getRecords($table,$db = array(),$select = "*",$ordercol = '',$group = '',$start='',$limit=''){
$this->db->select($select);
if(!empty($ordercol)){
$this->db->order_by($ordercol);
}
if($limit != '' && $start !=''){
$this->db->limit($limit,$start);
}
if($group != ''){
$this->db->group_by($group);
}
$q=$this->db->get_where($table, $db);
return $q->result_array();
}
// Get Recored row
public function getRecored_row($table,$where)
{
$q = $this->db->where($where)
->select('*')
->get($table);
return $q->row();
}
Check my answer: This code also working well, i have written, but i am not sure , this logic is correct or not kindly check this one.
public function checklead() {
$lead = $_POST['number'];
if($this->common_model->getRecords('leads',array("phone_no"=>$lead)))
{
$check=$this->common_model->getRecords('leads',array("phone_no"=>$lead));
}
else
{
$check=$this->common_model->getRecords('leads',array("landline_no"=>$lead));
}
echo "<pre>";
//echo $check;
//print_r($check); exit;
$p= $check[0]['phone_no'];
$l= $check[0]['landline_no'];
// exit;
if(count($p) > 0 || count($l)>0) {
$lead = $this->common_model->getRecored_row('leads',array("phone_no"=>$p));
$lead1 = $this->common_model->getRecored_row('leads',array("landline_no"=>$l));
if($lead->assignto_self != 0 || $lead1->assignto_self != 0) {
$assignto = $lead->assignto_self;
$key = 'Self Assign';
} else if($lead->assignto_se != 0 || $lead1->assignto_se != 0) {
$assignto = $lead->assignto_se;
$key = '';
}else if($lead->assignto_tl != 0 || $lead1->assignto_tl != 0) {
$assignto = $lead->assignto_tl;
$key = '';
} else if($lead->uploaded_by != 0 || $lead1->uploaded_by != 0) {
$assignto = $lead->uploaded_by;
$key = 'Uploaded by';
}
$user = $this->common_model->getRecored_row('admin',array("id"=>$assignto));
$role = $this->common_model->getRecored_row('role',array("id"=>$user->role));
$this->session->set_flashdata('message', array('message' => 'This Lead Already exist with '.$user->name.' ('.$role->role.') '.' ','class' => 'danger'));
redirect(base_url().'leads');
} else {
redirect(base_url().'leads/add_newlead/'.$lead);
}
}
There does not seem to be any reason to use getRecords(). The $check value has no useful purpose and creating it is a waste of resources.
We don't need $check because getRecord_row() will return the "lead" if found so the only check needed is to see if getRecord_row() returns anything. getRecord_row() uses the database function row() which returns only one row or null if no rows are found. Read about row() here.
If what you want is to find the "lead" that has either a "phone_no" or a "landline_no" equal to $_POST['number'] then you need to use a custom string for the where clause. (See #4 at on this documentation page.) You need a custom string because getRecord_row() does not allow any other way to ask for rows where a='foo' OR b='foo'. Here is what I think you are looking for.
public function checklead()
{
// use input->post() it is the safe way to get data from $_POST
$phone = $this->input->post('number');
// $phone could be null if $_POST['number'] is not set
if($phone)
{
$lead = $this->common_model->getRecored_row('leads', "phone_no = $phone OR landline_no = $phone");
// $lead could be null if nothing matches where condition
if($lead)
{
if($lead->assignto_self != 0)
{
$assignto = $lead->assignto_self;
$key = 'Self Assign';
}
else if($lead->assignto_se != 0)
{
$assignto = $lead->assignto_se;
$key = '';
}
}
}
}
The main difference between getRecords() and getRecord_row() is the number of records (rows of data) to return. getRecord_row() will return a maximum of one record while getRecords() might return many records.
getRecords() accepts arguments that allow control of what data is selected ($db, $select), how it is arranged ($ordercol, $group), and the number of rows to retrieve ($limit) starting at row number x ($start) .

Logical algorithm to generate paths

I'm trying to develop an algorithm to create a symfony template service.
I want to check if a template exists in a subset of paths, ordered.
Given an array of parameter like this (already ordered like I want):
$params = ['O', 'U', 'W', 'P']
How can I output this array?
$urls = [
'O/U/W/P/template',
'O/U/W/template',
'O/U/P/template',
'O/U/template',
'O/W/P/template',
'O/W/template',
'O/P/template',
'O/template',
'U/W/P/template',
'U/W/template',
'U/P/template',
'U/template',
'W/P/template',
'W/template',
'P/template',
'template'
];
I can perform for a little list of parameters (like everyone can do it I suppose) with a code like this :
private function getPaths($template, $params)
{
$urls = [];
$alreadyPerform = [];
$paramsCounter = count($params);
for ($i = 0; $i < $paramsCounter; $i++) {
for ($j = 0; $j < $paramsCounter; $j++) {
if ($i !== $j && !in_array($params[$j], $alreadyPerform, true)) {
$urls[] = sprintf(
'/%s/%s/%s.html.twig', $params[$i], $params[$j], $template
);
}
}
$alreadyPerform[] = $params[$i];
$urls[] = sprintf('/%s/%s.html.twig', $params[$i], $template);
}
$urls[] = sprintf('%s.html.twig', $template);
return $urls;
}
This function work like I wanted until today (max 3 parameters), but I want to add one parameters today, maybe more after.
Thank you very much for your help !
Cheers.
Using recursion, you can do the following:
/**
* #param array $elements
* #param array $extra
*
* #return Generator
*/
function gen(array $elements, array $extra = []): \Generator {
foreach ($elements as $i => $head) {
foreach (gen(array_slice($elements, $i + 1), $extra) as $tail) {
yield array_merge([$head], $tail);
}
}
yield $extra;
}
demo: https://3v4l.org/gJB8q
Or without recursion:
/**
* #param array $elements
*
* #return Generator
*/
function gen2(array $elements): \Generator {
for ($num = count($elements), $i = pow(2, $num) - 1; $i >= 1; $i -= 2) {
$r = [];
for ($j = 0; $j < $num; $j += 1) {
if ($i & (1 << ($num - $j - 1))) {
$r[] = $elements[$j];
}
}
yield $r;
}
}
demo: https://3v4l.org/grKXo
Consider using the following package:
https://github.com/drupol/phpermutations
Just a very basic example of what it can do:
$permutations = new \drupol\phpermutations\Generators\Permutations(['A', 'B', 'C'], 2);
foreach ($permutations->generator() as $permutation) {
echo implode('/', $permutation);
echo "\n";
}
A/B
B/A
A/C
C/A
B/C
C/B

How to prevent users from registering using diffrent characters than arabic with regex ?)

I want to prevent my visitors who want to become users in my websites from using Latin characters.
I want them to use only Arabic user names.
How to do that with regex and preg_match?
I think this has been answered here -> stackoverflow.com - How do I detect if an input string is Arabic
<?
function uniord($u) {
// i just copied this function fron the php.net comments, but it should work fine!
$k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
$k1 = ord(substr($k, 0, 1));
$k2 = ord(substr($k, 1, 1));
return $k2 * 256 + $k1;
}
function is_arabic($str) {
if(mb_detect_encoding($str) !== 'UTF-8') {
$str = mb_convert_encoding($str,mb_detect_encoding($str),'UTF-8');
}
/*
$str = str_split($str); <- this function is not mb safe, it splits by bytes, not characters. we cannot use it
$str = preg_split('//u',$str); <- this function woulrd probably work fine but there was a bug reported in some php version so it pslits by bytes and not chars as well
*/
preg_match_all('/.|\n/u', $str, $matches);
$chars = $matches[0];
$arabic_count = 0;
$latin_count = 0;
$total_count = 0;
foreach($chars as $char) {
//$pos = ord($char); we cant use that, its not binary safe
$pos = uniord($char);
echo $char ." --> ".$pos.PHP_EOL;
if($pos >= 1536 && $pos <= 1791) {
$arabic_count++;
} else if($pos > 123 && $pos < 123) {
$latin_count++;
}
$total_count++;
}
if(($arabic_count/$total_count) > 0.6) {
// 60% arabic chars, its probably arabic
return true;
}
return false;
}
$arabic = is_arabic('عربية إخبارية تعمل على مدار اليوم. يمكنك مشاهدة بث القناة من خلال الموقع');
var_dump($arabic);
?>
They also show a preg_match statement
$str = "بسم الله";
if (preg_match('/[أ-ي]/ui', $str)) {
echo "A match was found.";
} else {
echo "A match was not found.";
}
You could use the unicode property \p{Arabic}, see http://perldoc.perl.org/perluniprops.html
Using php:
preg_match('/^\p{Arabic}+$/u', $string, $matches);

How to use preg_replace_callback

I am trying to replace the 2nd occurrence of the $target_str.
If someone could explain how preg_replace_callback works I would appreciate it.
I don't understand the function($match) part. How do I set it so it matches the 2nd occurrence and only replaces that string?
I have the code (but it doesn't work as I want it to).
$replacement_params['target_str'] = "[\n]";
$replacement_params['replacement_str'] = "\n<ads media=googleAds1 />\n";
$target_str = $this->params['target_str'];
$replacement_str = $this->params['replacement_str'];
$num_matches;
$i = 0;
$new_text = preg_replace_callback("/".$target_str."/U",
function ( $match ) {
if ( $i === 1 ) {
return $replacement_str;
} else {
return $match[0];
}
$i++;
} , $article_text, 1, $num_matches );
Updated
Using built-in counter variable of preg_replace_callback:
$new_text = preg_replace_callback("/$target_str/U",
function($matches) use (&$count, $replacement_str)
{
$count++;
return ($count == 2) ? $replacement_str : $matches[0];
} , $article_text, -1, $count);

Magento hardcodes VARCHAR attributes to 255 length, any reason to not change this?

I have a requirement to save an Order Item attribute as a string up to 400 char. While it could be implemented using a text attribute, I would rather use a varchar(400). However, the _addFlatAttribute() method in Mage_Sales_Model_Resource_Setup hardcodes the length of varchar to 255. It could be changed after the fact by a setup script with DDL, but I'm wondering if there are likely to be downstream dependencies on VARCHAR being 255 char.
Any thoughts?
I believe that you will be fine & well-advised to do this given the ever-expanding size of order entity data in an instance. I'm curious what version of Magento though, as CE1.6+ is the first release to have the Mage_Sales_Model_Resource_Setup [link] class. Prior to CE1.6 the class was Mage_Sales_Model_Mysql4_Setup [link]. This is an important distinction because the column definition method in these classes differs to accomodate the DB-agnostic approach in 1.6+
Mage_Sales_Model_Mysql4_Setup::_getAttributeColumnDefinition [link]:
protected function _getAttributeColumnDefinition($code, $data)
{
$columnDefinition = '';
$type = isset($data['type']) ? $data['type'] : 'varchar';
$req = isset($data['required']) ? $data['required'] : false;
switch ($type) {
case 'int':
$columnDefinition = 'int(10) unsigned';
break;
case 'decimal':
$columnDefinition = 'decimal(12,4)';
break;
case 'text':
$columnDefinition = 'text';
break;
case 'date':
$columnDefinition = 'datetime';
break;
default:
$columnDefinition = 'varchar(255)';
break;
}
if ($req) {
$columnDefinition.= ' NOT NULL';
}
return $columnDefinition;
}
And Mage_Sales_Model_Resource_Setup::_getAttributeColumnDefinition [link]:
protected function _getAttributeColumnDefinition($code, $data)
{
// Convert attribute type to column info
$data['type'] = isset($data['type']) ? $data['type'] : 'varchar';
$type = null;
$length = null;
switch ($data['type']) {
case 'timestamp':
$type = Varien_Db_Ddl_Table::TYPE_TIMESTAMP;
break;
case 'datetime':
$type = Varien_Db_Ddl_Table::TYPE_DATETIME;
break;
case 'decimal':
$type = Varien_Db_Ddl_Table::TYPE_DECIMAL;
$length = '12,4';
break;
case 'int':
$type = Varien_Db_Ddl_Table::TYPE_INTEGER;
break;
case 'text':
$type = Varien_Db_Ddl_Table::TYPE_TEXT;
$length = 65536;
break;
case 'char':
case 'varchar':
$type = Varien_Db_Ddl_Table::TYPE_TEXT;
$length = 255;
break;
}
if ($type !== null) {
$data['type'] = $type;
$data['length'] = $length;
}
$data['nullable'] = isset($data['required']) ? !$data['required'] : true;
$data['comment'] = isset($data['comment']) ? $data['comment'] : ucwords(str_replace('_', ' ', $code));
return $data;
}
I can't imagine so, it might be different if you were to decrease the size of varchar, though.
See also:
Is there a good reason I see VARCHAR(255) used so often (as opposed to another length)?
Use type TEXT instead of VARCHAR. Mage_Sales_Model_Resource_Setup assumes a length of 64KB in this case.

Resources