Conditionally remove a word from a string? - php

I've found answers that are similar to the one I'm looking for, but not one that completely addresses my problem.
A user clicks a link on my page which takes them to Google Books and does a search. However, if the first word in the title of the book contains a contraction, everything gets thrown off and none of my corrections seem to work.
Example:
The link on my page looks like this:
mysite.com/book-search?bookauthor=Lance Armstrong&booktitle=It's Not About the Bike
However, when I run this:
$bookTitle = $_GET['booktitle']
I get the same title with the apostrophe in "It's" removed. And that's enough to completely throw off the Google Books Search and return no results.
The endpoint in the cURL session that does the search looks like this:
https://www.googleapis.com/books/v1/volumes?q=intitle:' . $bookTitle . '+inauthor:' . $bookAuthor;
Try it yourself -
https://www.googleapis.com/books/v1/volumes?q=intitle:It%27s+Not_About+The+Bike+inauthor:Lance+Armstrong
Returns a completely different result than
https://www.googleapis.com/books/v1/volumes?q=intitle:Its+Not_About+The+Bike+inauthor:Lance+Armstrong
You'd think that if I urlencoded the strings, that would solve the problem. But it doesn't. Still, for a reason that I can't fathom, when I do this:
$google_endpoint_a = 'https://www.googleapis.com/books/v1/volumes?q=intitle:' . urlencode($bookTitle) . '+inauthor:' . urlencode($bookAuthor);
...the urlencoding gets stripped out when it's passed to the GoogleAPI and I get a zero result search again.
Can somebody help me wade through this? I've tried everything I can think of.
OH - and here's the bonus - this ONLY happens if the first word in the string contains the apostrophe. So it happens with book titles like "It's Not About The Bike" and "Don't Blink". Apostrophes in other words don't seem to matter. (Like author Bill O'Reilly, for example.)
Is there an easy way to remove the first word from the string IF it contains an apostrophe? Or is there a better way?
The Really Ugly Solution:
So PHP passes $_GET variables through urldecode(). So even though it's ugly, here's what I ended up doing that solved the problem, even though I hope someone will come up with a better way.
Before I passed the variable through the URL, I replaced the apostrophe with a string of gibberish, like this:
$booktitle = str_replace("'", "W5x32RS97", $booktitle);
Then ran this:
$bookTitleTemp = $_GET('booktitle');
$bookTitle = str_replace("W5x32RS97", "'", $bookTitleTemp);
And suddenly, everything works. But there's GOT to be a better way.

Hadn't you try to subtitute the ' by \' in your title string? I mean, instead of:
It's Not About the Bike, using this: It\'s Not About the Bike

Without the apostrophe, you can drop intitle: and just use the following string:
$google_endpoint_a = 'https://www.googleapis.com/books/v1/volumes?q=' . urlencode($bookTitle) . '+inauthor:' . urlencode($bookAuthor);
https://www.googleapis.com/books/v1/volumes?q=Its+Not_About+The+Bike&inauthor:Lance+Armstrong
Update
To write a condition to use intitle if the first word has an apostrophe, you can do something like:
$pieces = explode(" ", $bookTitle);
if (strpos($pieces[0], "'") !== FALSE) {
$google_endpoint_a = 'https://www.googleapis.com/books/v1/volumes?q=' . urlencode($bookTitle) . '+inauthor:' . urlencode($bookAuthor);
}
else {
$google_endpoint_a = 'https://www.googleapis.com/books/v1/volumes?q=intitle:' . urlencode($bookTitle) . '+inauthor:' . urlencode($bookAuthor);
}
I would also see if encoding the variables earlier would work:
$bookTitle = urlencode($_GET[booktitle]);

in your link
use "It\'s"
not IT's

if you want to remove any apostrophe in the first word, then just test that the apostrophe has a lower string position than the first space. If it does, then remove it.
if(strpos($bookTitle,"'") < strpos($bookTitle," ")){
$bookTitle = preg_replace('/\'/', '', $bookTitle, 1);
}

Desperate diseases need desperate remedies.
$translation = array("aint" => "ain't", "arent" => "aren't", "cant" => "can't", "cantve" => "can't've", "cause" => "'cause", "couldve" => "could've", "couldnt" => "couldn't", "couldntve" => "couldn't've", "didnt" => "didn't", "doesnt" => "doesn't", "dont" => "don't", "hadnt" => "hadn't", "hadntve" => "hadn't've", "hasnt" => "hasn't", "havent" => "haven't", "hed" => "he'd", "hedve" => "he'd've", "hell" => "he'll", "hellve" => "he'll've", "hes" => "he's", "hows" => "how's", "Id" => "I'd", "Idve" => "I'd've", "Ill" => "I'll", "Illve" => "I'll've", "Im" => "I'm", "Ive" => "I've", "isnt" => "isn't", "itd" => "it'd", "itdve" => "it'd've", "itll" => "it'll", "itllve" => "it'll've", "its" => "it's", "lets" => "let's", "maam" => "ma'am", "mightve" => "might've", "mightnt" => "mightn't", "mightntve" => "mightn't've", "mustve" => "must've", "mustnt" => "mustn't", "mustntve" => "mustn't've", "oclock" => "o'clock", "oughtnt" => "oughtn't", "oughtntve" => "oughtn't've", "shant" => "shan't", "shantve" => "shan't've", "shed" => "she'd", "shedve" => "she'd've", "shell" => "she'll", "shellve" => "she'll've", "shes" => "she's", "shouldve" => "should've", "shouldnt" => "shouldn't", "shouldntve" => "shouldn't've", "sos" => "so's", "thats" => "that's", "thered" => "there'd", "theres" => "there's", "theyd" => "they'd", "theyll" => "they'll", "theyllve" => "they'll've", "theyre" => "they're", "theyve" => "they've", "wasnt" => "wasn't", "wed" => "we'd", "well" => "we'll", "wellve" => "we'll've", "were" => "we're", "weve" => "we've", "werent" => "weren't", "whatll" => "what'll", "whatllve" => "what'll've", "whatre" => "what're", "whats" => "what's", "whatve" => "what've", "whens" => "when's", "whenve" => "when've", "whered" => "where'd", "wheres" => "where's", "whereve" => "where've", "wholl" => "who'll", "whollve" => "who'll've", "whos" => "who's", "whove" => "who've", "whys" => "why's", "willve" => "will've", "wont" => "won't", "wontve" => "won't've", "wouldve" => "would've", "wouldnt" => "wouldn't", "wouldntve" => "wouldn't've", "yall" => "y'all", "yalldve" => "y'all'd've", "yallre" => "y'all're", "yallve" => "y'all've", "youd" => "you'd", "youdve" => "you'd've", "youll" => "you'll", "youllve" => "you'll've", "youre" => "you're", "youve" => "you've", );
$bookTitle = strtr($bookTitle, $translation);

Related

Cast double to int inside Smarty

I am trying to display double variable inside an Smarty environment converting it into int.
The File configuring the variables has the following code.
The Variable PRODUCTS_Quantity_x is the viewed Variable which I added. It is giving me a comma separated value with 3 fractional digits. The {$module_data.PRODUCTS_Quantity} is already be able to get displayed in through the html.
I have already tryed things like count() etc. I mostly got an empty variable or smarty errors ...
$t_data_array = array ( 'PRODUCTS_NAME' => htmlspecialchars_wrapper($array['products_name']),
'COUNT' => $array['ID'],
'PRODUCTS_ID' => $array['products_id'],
'PRODUCTS_VPE' => $this->getVPEtext($array, $products_price['plain']),
'PRODUCTS_IMAGE' => $this->productImage($array['products_image'], $image),
'PRODUCTS_IMAGE_W' => $array['products_image_w'],
'PRODUCTS_IMAGE_H' => $array['products_image_h'],
'PRODUCTS_IMAGE_WIDTH' => PRODUCT_IMAGE_THUMBNAIL_WIDTH,
'PRODUCTS_IMAGE_PADDING' => ((PRODUCT_IMAGE_THUMBNAIL_HEIGHT + 8) - $array['products_image_h'])/2,
'PRODUCTS_IMAGE_ALT' => $array['gm_alt_text'],
'PRODUCTS_LINK' => $gm_product_link,
'PRODUCTS_PRICE' => $products_price['formated'],
'PRODUCTS_TAX_INFO' => $gm_tax_info,
'PRODUCTS_SHIPPING_LINK' => $gm_shipping_link,
'PRODUCTS_BUTTON_BUY_NOW' => $buy_now,
'GM_PRODUCTS_BUTTON_BUY_NOW_URL' => $gm_buy_now_url,
'GM_PRODUCTS_BUTTON_BUY_NOW' => $gm_buy_now,
'PRODUCTS_SHIPPING_NAME' => $shipping_status_name,
'PRODUCTS_SHIPPING_IMAGE' => $shipping_status_image,
'PRODUCTS_DESCRIPTION' => $array['products_description'],
'PRODUCTS_EXPIRES' => $array['expires_date'],
'PRODUCTS_CATEGORY_URL' => $array['cat_url'],
'PRODUCTS_SHORT_DESCRIPTION' => $array['products_short_description'],
'PRODUCTS_FSK18' => $array['products_fsk18'],
'GM_FORM_ACTION' => xtc_draw_form('gm_add_to_cart_'.$array['products_id'], xtc_href_link('index.php', 'action=buy_now&BUYproducts_id=' . $array['products_id'] . $gm_cat_search, 'NONSSL', true, true, true), 'post', 'onsubmit="return gm_quantity_check_listing(\'' . $array['products_id'] . '\')"'),
'FORM_DATA' => $t_form_array,
'QTY_DATA' => $t_qty_array,
'PRODUCTS_Quantity_x' => $array['products_quantity'],
'GM_FORM_END' => '</form>',
'GM_PRODUCTS_QTY' => $gm_qty,
'GM_PRODUCTS_STOCK' => $gm_products_stock,
'PRODUCTS_META_DESCRIPTION' => $array['products_meta_description'],
'PRODUCTS_WEIGHT' => gm_prepare_number((double)$array['products_weight'], $xtPrice->currencies[$xtPrice->actualCurr]['decimal_point']),
'SHOW_PRODUCTS_WEIGHT' => $array['gm_show_weight']);
return $t_data_array;
// EOF GM_MOD
Inside the html the following code is given
<span class="label">{$module_data.PRODUCTS_Quantity_x}<span>
I hope you can help me out here
thanks in advance
You can do this 2 way:
1) First way:
You simple use in Smarty the following code with added string_format:
<span class="label">{$module_data.PRODUCTS_Quantity_x|string_format:"%d"}<span>
2) Second way:
You do whatever you need in PHP and assign desired value in PHP.
So in PHP you can change line:
'PRODUCTS_Quantity_x'=> $array['products_quantity'],
into
'PRODUCTS_Quantity_x'=> (int) $array['products_quantity'],
and then in Smarty you use the same code as you used earlier (without string_format):
<span class="label">{$module_data.PRODUCTS_Quantity_x}<span>

Displaying one string from a list of multiple strings

I'm trying to grab data from this array, but when I do var_dump($ArrayedLevels['Attack']); it returns NULL, I know for a fact that it was able to grab the data from the SQL database, I think it has something to do with my array. Any help would be greatly appreciated.
include("highscoresconfig.php");
$GrabXP = $database2->prepare("SELECT * FROM `skills` WHERE `playerName` = ?");
$GrabXP->execute(array($playerName));
$MainResult = $GrabXP->fetchAll();
$ArrayedLevels = $array = [
"Attack" => $MainResult['Attacklvl'],
"Defence" => $MainResult['Defencelvl'],
"Strength" => $MainResult['Strengthlvl'],
"Hitpoints" => $MainResult['Hitpointslvl'],
"Ranged" => $MainResult['Rangelvl'],
"Prayer" => $MainResult['Prayerlvl'],
"Magic" => $MainResult['Magiclvl'],
"Cooking" => $MainResult['Cookinglvl'],
"Woodcutting" => $MainResult['Woodcuttinglvl'],
"Fletching" => $MainResult['Fletchinglvl'],
"Fishing" => $MainResult['Fishinglvl'],
"Firemaking" => $MainResult['Firemakinglvl'],
"Crafting" => $MainResult['Craftinglvl'],
"Smithing" => $MainResult['Smithinglvl'],
"Mining" => $MainResult['Mininglvl'],
"Herblore" => $MainResult['Herblorelvl'],
"Agility" => $MainResult['Agilitylvl'],
"Thieving" => $MainResult['Thievinglvl'],
"Slayer" => $MainResult['Slayerlvl'],
"Farming" => $MainResult['Farminglvl'],
"Runecrafting" => $MainResult['Runecraftlvl'],
"Hunter" => $MainResult['Hunterlvl'],
"Construction" => $MainResult['Constructionlvl'],
"Summoning" => $MainResult['Summoninglvl'],
"Dungeoneering" => $MainResult['Dungeoneeringlvl'],
];
var_dump($ArrayedLevels["Attack"]);
Problem might be because the fetchAll() returns all the rows of your query.
if($GrabXP->execute(array($playerName))){
//Success
$MainResult = $GrabXP->fetchAll();
/*
This will give you all the rows. Use a foreach loop to iterate through all the rows.
If you want only the first row, add this-
*/
$MainResult = $MainResult[0];
//The rest of your code.
$ArrayedLevels = $array = Array(
"Attack" => $MainResult['Attacklvl'],
...
);
var_dump($ArrayedLevels["Attack"]);
}
else{
//Failure
}
The brackets don't work in PHP when creating a new array, use array() to create one.
Actually: as of PHP 5.4 they do work, see here: http://nl3.php.net/manual/en/language.types.array.php
Try var_dump($MainResult);
if all good, try create your array like this:
$ArrayedLevels = array(
"Attack" => $MainResult['Attacklvl'],
"Defence" => $MainResult['Defencelvl'],
"Strength" => $MainResult['Strengthlvl'],
"Hitpoints" => $MainResult['Hitpointslvl'],
"Ranged" => $MainResult['Rangelvl'],
"Prayer" => $MainResult['Prayerlvl'],
"Magic" => $MainResult['Magiclvl'],
"Cooking" => $MainResult['Cookinglvl'],
"Woodcutting" => $MainResult['Woodcuttinglvl'],
"Fletching" => $MainResult['Fletchinglvl'],
"Fishing" => $MainResult['Fishinglvl'],
"Firemaking" => $MainResult['Firemakinglvl'],
"Crafting" => $MainResult['Craftinglvl'],
"Smithing" => $MainResult['Smithinglvl'],
"Mining" => $MainResult['Mininglvl'],
"Herblore" => $MainResult['Herblorelvl'],
"Agility" => $MainResult['Agilitylvl'],
"Thieving" => $MainResult['Thievinglvl'],
"Slayer" => $MainResult['Slayerlvl'],
"Farming" => $MainResult['Farminglvl'],
"Runecrafting" => $MainResult['Runecraftlvl'],
"Hunter" => $MainResult['Hunterlvl'],
"Construction" => $MainResult['Constructionlvl'],
"Summoning" => $MainResult['Summoninglvl'],
"Dungeoneering" => $MainResult['Dungeoneeringlvl'],
);
first of all try to print the structure of the variable $MainResult:
var_dump($MainResult);
FetchAll return an array with all restuls like
resutl = [
[0] => ['first row'],
[1] => ['sec. row']
]
you will See The variable $MainResult looks like:
MailResult => [
[0] => ['Attacklvl' => 'foo'],
[1] => ['Defencelvl' => 'bar']
]

search php assoc array (hash map) as mysql

example
public $inputs=array(
array( 'sysname'=>'pt_name','dbname' => 'users.name','label' => 'user (name/ID)','value' => '',
'type' => 'text','rules' => 'required','attr'=>'class="autocomplete"'),
array( 'sysname'=>'pt_dob','dbname' => 'users.dob','label' => 'Patient Dob','value' => '',
'type' => 'text','rules' => 'required','attr'=>'class="dob ac" Disabled'),
array( 'sysname'=>'pt_gender','dbname' => 'users.gender','label' => 'gender','value' => 'male,female',
'type' => 'dropdown','rules' => 'required','attr'=>'class="ac" Disabled'),
array( 'sysname'=>'visit_date','dbname' => 'visits.date','label' => 'Date','value' => '',
'type' => 'text','rules' => 'required','attr'=>'class="datepicker"'),
array( 'sysname'=>'visit_time','dbname' => 'visits.time_booked','label' => 'Time','value' => '',
'type' => 'text','rules' => 'required','attr'=>'class="timepicker"'),
array( 'sysname'=>'visit_type','dbname' => 'visits.type','label' => 'Visit type','value' => 'visit,schedule',
'type' => 'dropdown','rules' => 'required','attr'=>'')
);
how can i search this array for only arrays that have pt_ in its sysname for example ?
the idea is i have many types of rows all in same table, so instead of running a mysql query to fetch each type separatly example:
$pt=db->query("select * from table where sysname like 'pt_%'")->result();
$visit=db->query("select * from table where sysname like 'visit_%'")->result();
i want to fetch all at one and split them in php to decrease db load.
so how can i do this ? and is it worth it or better of keep my querys separate.
array_filter and a PHP-style closure* would be a pretty simple solution to this:
function buildFilter($key, $needle) {
return function($array) use($key, $needle) {
return (strpos($array[$key], $needle) !== FALSE);
};
}
$matches = array_filter($inputs, buildFilter('sysname', 'pt_'));
var_dump($matches);
NB: What PHP calls a "closure" is quite a bit different from what most other languages use for the same term, so please make sure to read the PHP documentation.
Doing a couple of queries is fine, your DB can handle that easily. If you're doing dozens of queries for dozens of types (each with only a few rows), it might be worth investigation moving that logic to PHP.
What I would recommend is to put the systype in a separate column with an index on it. That will speed of your query a lot and take load of your DB. Even better is you can make that column an ENUM.
public $inputs=array(
array( 'systype'=>'pt', 'sysname'=>'pt_name','dbname' => 'users.name','label' => 'user (name/ID)','value' => '',
'type' => 'text','rules' => 'required','attr'=>'class="autocomplete"'),
...
$pt=db->query("select * from table where systype = 'pt'")->result();
$visit=db->query("select * from table where systype = 'visit'")->result();

PHPcassa insert randomly

$column_family->insert('row_key1', array('col_name1' => 'col_val1'));
$column_family->insert('row_key2', array('col_name2' => 'col_val2'));
$column_family->insert('row_key3', array('col_name3' => 'col_val3'));
$column_family->insert('row_key4', array('col_name4' => 'col_val4'));
The problem is mystery when the insert function does not insert value in sequence, instead it would appear in jumpping order: col_val2,col_val3,col_val1,col_val4
It bad when I could do a properly get_range() value as some have appear to insert into other partition.
How do I make the code insert orderly?
Have you tried using the batch_insert functionality?
$column_family->batch_insert(array(
'row_key1' => array('col_name1' => 'col_val1'),
'row_key2' => array('col_name2' => 'col_val2'),
'row_key3' => array('col_name3' => 'col_val3'),
'row_key4' => array('col_name4' => 'col_val4')
));

making IPTC data searchable

I have a question about IPTC metadata. Is it possible to search images that aren't in a database by their IPTC metadata (keywords) and show them and how would I go about doing this? I just need a basic idea.
I know there is the iptcparse() function for PHP.
I have already written a function to grab the image name, location, and extension for all images within a galleries folder and all subdirectories by .jpg extension.
I need to figure out how to extract the metadata without storing it in a database and how to search through it, grab the relevant images that match the search tag (their IPTC keywords should match) and how to display them. I know at the point that I have the final results (post search) i can echo an imagetag with src="$filelocation"> if i have the final results in an array.
Basically, I am not sure if I need to store all my images into a mysql database and also extract the keywords and store them in the database as well before I can actually search and display the results. Also, if you could guide me to any gallery that already is able to do this, that could help as well.
Thanks for any help regarding this issue.
It is not clear what in particular is giving you problems, but perhaps this will give you some ideas:
<?php
# Images we're searching
$images = array('/path/to/image.jpg', 'another-image.jpg');
# IPTC keywords to values (from exiv2, see below)
$query = array('Byline' => 'Some Author');
# Perform the search
$result = select_jpgs_by_iptc_fields($images, $query);
# Display the results
foreach ($result as $path) {
echo '<img src="', htmlspecialchars($path), '">';
}
function select_jpgs_by_iptc_fields($jpgs, $query) {
$matches = array();
foreach ($jpgs as $path) {
$iptc = get_jpg_iptc_metadata($path);
foreach ($query as $name => $values) {
if (!is_array($values))
$values = array($values);
if (count(array_intersect($iptc[$name], $values)) != count($values))
continue 2;
}
$matches[] = $path;
}
return $matches;
}
function get_jpg_iptc_metadata($path) {
$size = getimagesize($path, $info);
if(isset($info['APP13']))
{
return human_readable_iptc(iptcparse($info['APP13']));
}
else {
return null;
}
}
function human_readable_iptc($iptc) {
# From the exiv2 sources
static $iptc_codes_to_names =
array(
// IPTC.Envelope-->
"1#000" => 'ModelVersion',
"1#005" => 'Destination',
"1#020" => 'FileFormat',
"1#022" => 'FileVersion',
"1#030" => 'ServiceId',
"1#040" => 'EnvelopeNumber',
"1#050" => 'ProductId',
"1#060" => 'EnvelopePriority',
"1#070" => 'DateSent',
"1#080" => 'TimeSent',
"1#090" => 'CharacterSet',
"1#100" => 'UNO',
"1#120" => 'ARMId',
"1#122" => 'ARMVersion',
// <-- IPTC.Envelope
// IPTC.Application2 -->
"2#000" => 'RecordVersion',
"2#003" => 'ObjectType',
"2#004" => 'ObjectAttribute',
"2#005" => 'ObjectName',
"2#007" => 'EditStatus',
"2#008" => 'EditorialUpdate',
"2#010" => 'Urgency',
"2#012" => 'Subject',
"2#015" => 'Category',
"2#020" => 'SuppCategory',
"2#022" => 'FixtureId',
"2#025" => 'Keywords',
"2#026" => 'LocationCode',
"2#027" => 'LocationName',
"2#030" => 'ReleaseDate',
"2#035" => 'ReleaseTime',
"2#037" => 'ExpirationDate',
"2#038" => 'ExpirationTime',
"2#040" => 'SpecialInstructions',
"2#042" => 'ActionAdvised',
"2#045" => 'ReferenceService',
"2#047" => 'ReferenceDate',
"2#050" => 'ReferenceNumber',
"2#055" => 'DateCreated',
"2#060" => 'TimeCreated',
"2#062" => 'DigitizationDate',
"2#063" => 'DigitizationTime',
"2#065" => 'Program',
"2#070" => 'ProgramVersion',
"2#075" => 'ObjectCycle',
"2#080" => 'Byline',
"2#085" => 'BylineTitle',
"2#090" => 'City',
"2#092" => 'SubLocation',
"2#095" => 'ProvinceState',
"2#100" => 'CountryCode',
"2#101" => 'CountryName',
"2#103" => 'TransmissionReference',
"2#105" => 'Headline',
"2#110" => 'Credit',
"2#115" => 'Source',
"2#116" => 'Copyright',
"2#118" => 'Contact',
"2#120" => 'Caption',
"2#122" => 'Writer',
"2#125" => 'RasterizedCaption',
"2#130" => 'ImageType',
"2#131" => 'ImageOrientation',
"2#135" => 'Language',
"2#150" => 'AudioType',
"2#151" => 'AudioRate',
"2#152" => 'AudioResolution',
"2#153" => 'AudioDuration',
"2#154" => 'AudioOutcue',
"2#200" => 'PreviewFormat',
"2#201" => 'PreviewVersion',
"2#202" => 'Preview',
// <--IPTC.Application2
);
$human_readable = array();
foreach ($iptc as $code => $field_value) {
$human_readable[$iptc_codes_to_names[$code]] = $field_value;
}
return $human_readable;
}
If you don't have extracted those IPTC data from your images, each time someone will search, you'll have to :
loop on every images
for each image, extract the IPTC data
see if the IPTC data for the current image matches
If you have more than a couple image, this will be really bad for performances, I'd say.
So, in my opinion, it would be far better to :
add a couple of fields in your database
extract the relevant IPTC data when the image is uploaded / stored
store the IPTC data in those DB fields
search in those DB fields
Or use some search engine like Lucene or Sphinx -- but that is another problem.
It'll mean a bit more work for you right now : you have more code to write...
... But it also means your website will have better chances to survive when there are several images and many users doing searches.

Categories