Problem with numbers and nonexistence - php

So I have a script that includes forms that are stored in files named like 0101, 0102, and the next category would be 0201, 0202, 0203. The first two set of numbers are the category, second set are the pages in for the forms.
The problem I am having with this numbering is that I am storing the number as 0101 or 0205 and since the first number is only a non-existent thing, 0, it seems to be knocking it off. The only way I managed to actually make it work in some messy way was to do something like this:
"planpages/0" . $nextcat . ".php"
Where $nextcat might be 203. It doesn't seem to like the 0 in front of anything, and must be stored in a string which has something before it (in the case above, you have a "/" sign).
How do I solve the problem with data loss? I did try looking it up in other places, but I didn't know what to put in for the query.
EDIT: More code.
The number is originally stored in $_GET['content'], passed to nextForm($current).
function nextForm($current) {
$next = $current[0] . $current[1] . $current[2] . $current[3] + 1;
$nextcat = $current[0] . $current[1] + 1 . 0 . 1;
if(file_exists("planpages/0" . $next . ".php")) {
return "0" . $next;
} elseif(file_exists("planpages/0" . $nextcat . ".php")) {
return "0" . $nextcat;
} else {
return $current;
}
}
Hopefully that is more information needed. It looks like a mess because I tried my hardest to keep those zeros, but they keep disappearing.

You can zero-pad with sprintf:
$form = 1;
$page = 2;
$string = sprintf('%02d%02d', $form, $page);
This will give you:
$string = '0102';
Or if you have:
$value = 102;
Then:
$string = sprintf('%04d', $value);

Maybe you should use str_pad to zero-pad category and page.
$category = 2;
$pages = 1;
$cat = str_pad($category, 2, "0", STR_PAD_LEFT);
$pag = str_pad($pages, 2, "0", STR_PAD_LEFT);
$filename = $cat . $pag;
// $filename = "0201"

Related

Support negative values

I'm in a situation where the CSV file is getting rid of the leading zero before my import and I need to be able to account for that. Let's say that I have my value as the following:
-.0982739 -> I would want all case scenarios where it's -. to turn into -0. - Here are my attempts:
if (str_contains($this->longitude, '-.')) {
$this->longitude = '0' . $this->longitude;
};
Outputs: 00-.0989070
if ($this->longitude[0] == '.') {
$this->longitude = '0' . $this->longitude;
}
Outputs: -.0989070
To simplify things, basically any . that has nothing before it, add in a 0, otherwise use the value given.
I will need it for both longitude and latitude.
/^([-+])?\./
The above regex matches the signs - and + if they are present and immediately followed by a .. Now, capture the matched group 1 in the regex which is ([-+])? and append 0. followed by all digits after . by taking substr of the current string.
<?php
$a = ".0982739";
if(preg_match('/^([-+])?\./',$a, $matches) === 1){
$prefix = $matches[1] ?? '';
$a = $prefix . '0.' . substr($a,$prefix == '' ? 1 : 2);
}
echo $a;
Try this :
<?php
$x = -.54321 ;
echo $x . "\r\n" ;
$x = "-.12345" ;
echo $x . "\r\n" ;
echo floatval($x) . "\r\n" ;
echo sprintf("%0.5f", $x) ;
?>
I assume your CSV is returning only string values, because as soon as I echo a "native" float, the echo is just fine.
As soon as your float is correctly formatted, you can catch it in a string value if needed.
You could use str_replace:
$this->longitude = ltrim($this->longitude, '+');// remove leading +
if ($this->longitude[0]=='.' || substr($this->longitude, 0, 2)=='-.')) {
$this->longitude = str_replace('.', '0.', $this->longitude);
}
The if condition matches any string that begins with '.' or '-.' And if so, str_replace replaces the . with 0.
`$var = 0.0989070;
$neg = -$var; // easiest
$neg = -1 * $var; // bit more explicit
$neg = 0 - $var; // another version`
You could check for numbers before dot....
<?php
if (str_contains($this->longitude, '.')) {
$beforedot = strstr($this->longitude,'.',true); //Get anything before
if (is_numeric($beforedot)) { echo "do nothing"; } //check if is number do nothing
else {
$this->longitude = str_replace('.', '0.', $this->longitude); //else do replace . with 0.
}
};
?>
I created a class and assigned -.0982739 to a property called $longitude. In the constructor I did echo $this->longitude and it came out as -0.0982739 which I believe is exactly as you want it to be. I couldn't manage to reproduce it.
<?php
class Test
{
private $longitude = -.0982739;
public function __construct()
{
}
public function test()
{
echo $this->longitude;
}
}
<?php
include "Test.php";
$test = new Test();
$test->test();

Trying to find a way to take a series of values in a json array and add them to an int

Here is my PHP function that grabs data from inputs on the page.
function getCounts($selection, $srch) {
$loadjson = file_get_contents('data.json');
$jsondata = json_decode($loadjson);
$total = 0;
foreach ($jsondata as $list) {
if ($list->$selection == $srch) {
$total .= $list->TOTAL
}
}
echo 'Total - ' . $total . '<br>' . '<br>';
}
I know the issue is with the line "$total .= $list->TOTAL" but I cannot figure out how to take the value that "$list->TOTAL" gets and add it to an integer. I have tested and if I do "echo $list->TOTAL . ','" instead of "$total .= $list->TOTAL" the function spits out a list of all the numbers that are in the JSON data I simply cannot figure out how to get the numbers into an integr and added into one number.
Can someone point me in the right direction?

Php simple algorithm for autoloader

Here's my "simple" algorithm:
if the class is named like 'AaaBbbCccDddEeeFff' loop like this:
include/aaa/bbb/ccc/ddd/eee/fff.php
include/aaa/bbb/ccc/ddd/eee_fff.php
include/aaa/bbb/ccc/ddd_eee_fff.php
include/aaa/bbb/ccc_ddd_eee_fff.php
include/aaa/bbb_ccc_ddd_eee_fff.php
include/aaa_bbb_ccc_ddd_eee_fff.php
if still nothing found, try to look if those files exist:
include/aaa/bbb/ccc/ddd/eee/fff/base.php
include/aaa/bbb/ccc/ddd/eee/base.php
include/aaa/bbb/ccc/ddd/base.php
include/aaa/bbb/ccc/base.php
include/aaa/bbb/base.php
include/aaa/base.php
include/base.php
If still not found then error.
I'm looking for a fast and easy way to convert this:
'AaaBbbCccDddEeeFff'
to this:
include/aaa/bbb/ccc/ddd/eee/fff.php
and then and easy way to remove latest folder (I guess I should look for explode()).
Any idea how to do this? (I'm not asking for the whole code, I'm not lazy).
Since you specifically asked not to have the whole code, here is some code to get you started. This takes the input and divides it into chunks delineated by changes in case. The rest you can work out as an exercise.
<?php
$input = "AaaBbbCccDddEeeFff";
$str_so_far = "";
$last_was_upper = 0;
$chunks = array();
while($next_letter = substr($input,0,1)) {
$is_upper = (strtoupper($next_letter)==$next_letter);
if($str_so_far && $is_upper && !$last_was_upper) {
$chunks[] = $str_so_far;
$str_so_far = "";
}
if($str_so_far && !$is_upper && $last_was_upper) {
$chunks[] = $str_so_far;
$str_so_far = "";
}
$str_so_far .= $next_letter;
$input = substr($input,1);
$last_was_upper = $is_upper;
}
var_dump($chunks);
?>
I think a regular expression would work. Something like preg_match_all('[A-Z][a-z][a-z]'
, $string); might work - that would match a capital letter, followed by a lowercase letter, and another lowercase letter.
As the other answers are regex, here's a non-regex way for completeness:
function transform($str){
$arr = array();
$part = '';
for($i=0; $i<strlen($str); $i++){
$char = substr($str, $i, 1);
if(ctype_upper($char) && $i > 0){
$arr[] = $part;
$part = '';
}
$part .= $char;
}
$arr[] = $part;
return 'include/' . strtolower(implode('/', $arr)) . '.php';
}
echo transform('AaaBbbCccDddEeeFff');
// include/aaa/bbb/ccc/ddd/eee/fff.php
This builds an array of the folders, so you can manipulate it as needed, for example remove a folder by unsetting the desired index, before it gets imploded.
Here is the first part of your algorithm:
AaaBbbCccDddEeeFff -> include/aaa/bbb/ccc/ddd/eee/fff.php
include/aaa/bbb/ccc/ddd/eee_fff.php
include/aaa/bbb/ccc/ddd_eee_fff.php
include/aaa/bbb/ccc_ddd_eee_fff.php
include/aaa/bbb_ccc_ddd_eee_fff.php
include/aaa_bbb_ccc_ddd_eee_fff.php
I think you can do last part independently based on my answer.
<?php
function convertClassToPath($class) {
return strtolower(preg_replace('/([a-z])([A-Z])/', '$1' . DIRECTORY_SEPARATOR . '$2', $class)) . '.php';
}
function autoload($path) {
$base_dir = 'include' . DIRECTORY_SEPARATOR;
$real_path = $base_dir . $path;
var_dump('Checking: ' . $real_path);
if (file_exists($real_path) === true) {
var_dump('Status: Success');
include $real_path;
} else {
var_dump('Status: Fail');
$last_separator_pos = strrpos($path, DIRECTORY_SEPARATOR);
if ($last_separator_pos === false) {
return;
} else {
$path = substr_replace($path, '_', $last_separator_pos, 1);
autoload($path);
}
}
}
$class = 'AaaBbbCccDddEeeFff';
var_dump(autoload(convertClassToPath($class)));

Place content in between paragraphs without images

I am using the following code to place some ad code inside my content .
<?php
$content = apply_filters('the_content', $post->post_content);
$content = explode (' ', $content);
$halfway_mark = ceil(count($content) / 2);
$first_half_content = implode(' ', array_slice($content, 0, $halfway_mark));
$second_half_content = implode(' ', array_slice($content, $halfway_mark));
echo $first_half_content.'...';
echo ' YOUR ADS CODE';
echo $second_half_content;
?>
How can i modify this so that the 2 paragraphs (top and bottom) enclosing the ad code should not be the one having images. If the top or bottom paragraph has image then try for next 2 paragraphs.
Example: Correct Implementation on the right.
preg_replace version
This code steps through every paragraph ignoring those that contain image tags. The $pcount variable is incremented for every paragraph found without an image, if an image is encountered however, $pcount is reset to zero. Once $pcount reaches the point where it would hit two, the advert markup is inserted just before that paragraph. This should leave the advert markup between two safe paragraphs. The advert markup variable is then nullified so only one advert is inserted.
The following code is just for set up and could be modified to split the content differently, you could also modify the regular expression that is used — just in case you are using double BRs or something else to delimit your paragraphs.
/// set our advert content
$advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n";
/// calculate mid point
$mpoint = floor(strlen($content) / 2);
/// modify back to the start of a paragraph
$mpoint = strripos($content, '<p', -$mpoint);
/// split html so we only work on second half
$first = substr($content, 0, $mpoint);
$second = substr($content, $mpoint);
$pcount = 0;
$regexp = '/<p>.+?<\/p>/si';
The rest is the bulk of the code that runs the replacement. This could be modified to insert more than one advert, or to support more involved image checking.
$content = $first . preg_replace_callback($regexp, function($matches){
global $pcount, $advert;
if ( !$advert ) {
$return = $matches[0];
}
else if ( stripos($matches[0], '<img ') !== FALSE ) {
$return = $matches[0];
$pcount = 0;
}
else if ( $pcount === 1 ) {
$return = $advert . $matches[0];
$advert = '';
}
else {
$return = $matches[0];
$pcount++;
}
return $return;
}, $second);
After this code has been executed the $content variable will contain the enhanced HTML.
PHP versions prior to 5.3
As your chosen testing area does not support PHP 5.3, and so does not support anonymous functions, you need to use a slightly modified and less succinct version; that makes use of a named function instead.
Also, in order to support content that may not actually leave space for the advert in it's second half I have modified the $mpoint so that it is calculated to be 80% from the end. This will have the effect of including more in the $second part — but will also mean your adverts will be generally placed higher up in the mark-up. This code has not had any fallback implemented into it, because your question does not mention what should happen in the event of failure.
$advert = '<marquee>BUY THIS STUFF!!</marquee>' . "\n\n";
$mpoint = floor(strlen($content) * 0.8);
$mpoint = strripos($content, '<p', -$mpoint);
$first = substr($content, 0, $mpoint);
$second = substr($content, $mpoint);
$pcount = 0;
$regexp = '/<p>.+?<\/p>/si';
function replacement_callback($matches){
global $pcount, $advert;
if ( !$advert ) {
$return = $matches[0];
}
else if ( stripos($matches[0], '<img ') !== FALSE ) {
$return = $matches[0];
$pcount = 0;
}
else if ( $pcount === 1 ) {
$return = $advert . $matches[0];
$advert = '';
}
else {
$return = $matches[0];
$pcount++;
}
return $return;
}
echo $first . preg_replace_callback($regexp, 'replacement_callback', $second);
You could try this:
<?php
$ad_code = 'SOME SCRIPT HERE';
// Your code.
$content = apply_filters('the_content', $post->post_content);
// Split the content at the <p> tags.
$content = explode ('<p>', $content);
// Find the mid of the article.
$content_length = count($content);
$content_mid = floor($content_length / 2);
// Save no image p's index.
$last_no_image_p_index = NULL;
// Loop beginning from the mid of the article to search for images.
for ($i = $content_mid; $i < $content_length; $i++) {
// If we do not find an image, let it go down.
if (stripos($content[$i], '<img') === FALSE) {
// In case we already have a last no image p, we check
// if it was the one right before this one, so we have
// two p tags with no images in there.
if ($last_no_image_p_index === ($i - 1)) {
// We break here.
break;
}
else {
$last_no_image_p_index = $i;
}
}
}
// If no none image p tag was found, we use the last one.
if (is_null($last_no_image_p_index)) {
$last_no_image_p_index = ($content_length - 1);
}
// Add ad code here with trailing <p>, so the implode later will work correctly.
$content = array_slice($content, $last_no_image_p_index, 0, $ad_code . '</p>');
$content = implode('<p>', $content);
?>
It will try to find a place for the ad from the mid of your article and if none is found the ad is put to the end.
Regards
func0der
I think this will work:
First explode the paragraphs, then you have to loop it and check if you find img inside them.
If you find it inside, you try the next.
Think of this as psuedo-code, since it's not tested. You will have to make a loop too, comments in the code :) Sorry if it contains bugs, it's written in Notepad.
<?php
$i = 0; // counter
$arrBoolImg = array(); // array for the paragraph booleans
$content = apply_filters('the_content', $post->post_content);
$contents = str_replace ('<p>', '<explode><p>', $content); // here we add a custom tag, so we can explode
$contents = explode ('<explode>', $contents); // then explode it, so we can iterate the paragraphs
// fill array with boolean array returned
$arrBoolImg = hasImages($contents);
$halfway_mark = ceil(count($contents) / 2);
/*
TODO (by you):
---
When you have $arrBoolImg filled, you can itarate through it.
You then simply loop from the middle of the array $contents (plural), that is exploded from above.
The startingpoing for your loop is the middle, the upper bounds is the +2 or what ever :-)
Then you simply insert your magic.. And then glue it back together, as you did before.
I think this will work. even though the code may have some bugs, since I wrote it in Notepad.
*/
function hasImages($contents) {
/*
This function loops through the $contents array and checks if they have images in them
The return value, is an array with boolean values, so one can iterate through it.
*/
$arrRet = array(); // array for the paragraph booleans
if (count($content)>=1) {
foreach ($contents as $v) { // iterate the content
if (strpos($v, '<img') === false) { // did not find img
$arrRet[$i] = false;
}
else { // found img
$arrRet[$i] = true;
}
$i++;
} // end for each loop
return $arrRet;
} // end if count
} // end hasImages func
?>
[This is just an idea, I don't have enough reputation to comment...]
After calling #Olavxxx's method and filling your boolean array you could just loop through that array in an alternating manner starting in the middle: Let's assume your array is 8 entries long. Calculating the middle using your method you get 4. So you check the combination of values 4 + 3, if that doesn't work, you check 4 + 5, after that 3 + 2, ...
So your loop looks somewhat like
$middle = ceil(count($content) / 2);
$i = 1;
while ($i <= $middle) {
$j = $middle + (-1) ^ $i * $i;
$k = $j + 1;
if (!$hasImagesArray[$j] && !$hasImagesArray[$k])
break; // position found
$i++;
}
It's up to you to implement further constraints to make sure the add is not shown to far up or down in the article...
Please note that you need to take care of special cases like too short arrays too in order to prevent IndexOutOfBounds-Exceptions.

Random image picker PHP

$images = array();
$images[0][0] = "boxes/blue.jpg";
$images[0][1] = "blah.html";
$images[1][0] = "boxes/green.jpg";
$images[1][1] = "blah.html";
$images[2][0] = "boxes/orange.jpg";
$images[2][1] = "blah.html";
$images[3][0] = "boxes/pink.jpg";
$images[3][1] = "blah.html";
$images[4][0] = "boxes/purple.jpg";
$images[4][1] = "blah.html";
$images[5][0] = "boxes/red.jpg";
$images[5][1] = "blah.html";
$images[6][0] = "boxes/yellow.jpg";
$images[6][1] = "blah.html";
$i = 0;
*echo "<a href='" . $images[0][1] . "'><img src='" . $images[0][0] . "' /></a>";
$boxes = array();
while($i<5)
{
$rand = rand(0,(sizeof($images)-1));
//echo $rand;
$slice = array_splice($images, $rand);
$boxes[$i] = $slice;
$i++;
}*
I am trying to get a random image picker to choose from a list of images provided by the $images array. However, I am unable to fill the $boxes array with anything other than "Array". Can anyone tell me why? Any help is much appreciated
UPDATE
I am now using the code below and it breaks whenever it comes across an empty element. Unless i am very much mistaken, shouldn't splice patch up holes like that?
$rand = rand(0,(sizeof($images)));
array_splice($images, $rand);
$i = 0;
while($i<5)
{
echo "<a href='" . $images[$i][1] . "'><img src='" . $images[$i][0] . "' /></a>";
$i++;
}
This might be a nicer way of doing it:
foreach (array_rand($images, 5) as $key) {
$boxes[] = $images[$key];
}
Slightly off topic, but wouldn't it be easier in this case (picking 5 items from a list of 6) just to pick one element and discard it from the original array, and then use the original? This will also ensure you do not get duplicates in the resultant array.
I realise that you may have more than 6 items in the original, and may want less than 5 from it, but I'm talking specifically about the example posted.
array_splice() returns an array.
You can try something like this:
while($i<5)
{
$rand = rand(0,(sizeof($images)-1));
$boxes[$i] = $images[$rand];
$i++;
}

Categories