I'm trying to run a find replace of multiple values to do a mail merge effect on an HTML signature stored in the database.
I can get the string part replaced no worries, but for some reason it's leaving the "[" & "]" behind in the output.
Merge tags in the HTML would look like this: [FirstName], [LastName]
Original HTML would look like this:
Kind regards
[FirstName] [LastName]
After running the mailmerge function it should look like this:
Kind regards
John Smith
Here is what I've come up with so far, and Im sure the issue is something small:
public function merge_user_signature() {
$user = $this->get_user_by_id();
//spit_out($user);
$authorisedMergeTags = array (
"[FirstName]" => $user->firstName,
"[LastName]" => $user->lastName
);
$keys = array_keys($authorisedMergeTags);
$values = array_values($authorisedMergeTags);
$html = $this->get_user_signature();
$mergedSignature = preg_replace($keys, array_values($authorisedMergeTags), $html);
return $mergedSignature;
}
Thanks in advance
You don't need to use a regex to deal with literal strings (whatever the situation):
return strtr($html, $authorisedMergeTags);
Related
The concept is that, after a successfull save of my object, it should update a text in the database (With a Hook). Lets call the field 'succText'. The table i would like to access is the sys_file but i only get the sys_file_reference id when i save the object. So i thought i could use the ConnectionPool to select the sys_file row of this file reference and then insert the data on the field 'succText'.
I tried this:
public function processDatamap_preProcessFieldArray(array &$fieldArray, $table, $id, \TYPO3\CMS\Core\DataHandling\DataHandler &$pObj) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
$findItemsId = $queryBuilder
->select('*')
->from('sys_file_reference')
->join(
'sys_file_reference',
'sys_file',
'reference',
$queryBuilder->expr()->eq('reference.uid', $queryBuilder->quoteIdentifier('uid_local'))
)
->where(
$queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter($fieldArray['downloads'], \PDO::PARAM_INT))
)
->execute();
}
But this give me back the sys_file_reference id and not the id and the field values of the sys_file table.
As for the update, i havent tried it yet, cause i haven't figured out yet, how to get the row that needs to be updated. I gues with a subquery after the row is found, i don't really know.
The processDatamap_preProcessFieldArray is going to be renamed to post. I only have it this way in order to get the results on the backend.
Thanks in advance,
You might want to make use of the FileRepository class here.
$fileRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\FileRepository::class);
$fileObjects = $fileRepository->findByRelation('tablename', 'fieldname', $uid);
Where $uid is the ID of the record that the files are connected to via file reference.
You will get back an array of file objects to deal with.
I resolved my problem by removing the first code and adding a filerepository instance.
$fileRepository = GeneralUtility::makeInstance(FileRepository::class);
$fileObjects = $fileRepository->findByRelation('targetTable', 'targetField', $uid);
VERY IMPORTANT!
If you are creating a new element then TYPO3 assigns a temp UID variable with a name that looks like this NEW45643476. In order to get the $uid from the processDatamap_afterDatabaseOperations you need to add this code before you get the instance of the fileRepository.
if (GeneralUtility::isFirstPartOfStr($uid, 'NEW')) {
$uid = $pObj->substNEWwithIDs[$uid];
}
Now as far as the text concerns, i extracted from a pdf. First i had to get the basename of the file in order to find its storage location and its name. Since i have only one file i don't really need a foreach loop and i can use the [0] as well. So the code looked like this:
$fileID = $fileObjects[0]->getOriginalFile()->getProperties()['uid'];
$fullPath[] = [PathUtility::basename($fileObjects[0]->getOriginalFile()->getStorage()->getConfiguration()['basePath']), PathUtility::basename($fileObjects[0]->getOriginalFile()->getIdentifier())];
This, gives me back an array looking like this:
array(1 item)
0 => array(2 items)
0 => 'fileadmin' (9 chars)
1 => 'MyPdf.pdf' (9 chars)
Now i need to save the text from every page in a variable. So the code looks like this:
$getPdfText = '';
foreach ($fullPath as $file) {
$parser = new Parser();
$pdf = $parser->parseFile(PATH_site . $file[0] . '/' . $file[1]);
$pages = $pdf->getPages();
foreach ($pages as $page) {
$getPdfText .= $page->getText();
}
}
Now that i have my text i want to add it on the database so i will be able to use it on my search action. I now use the connection pool to get the file from the sys_file.
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file');
$queryBuilder
->update('sys_file')
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($fileID))
)
->set('pdf_text', $getPdfText)
->execute();
Now everytime i choose a PDF from my extension, i save its text on the database.
EXTRA CONTENT
If you want to include the PDFParser as well and you are on composer mode, then add this on your composer.json:
"smalot/pdfparser" : "*"
and on the autoload:
"Smalot\\PdfParser\\" : "Packages/smalot/pdfparser/src/"
Then under: yourExtension/Classes/Hooks/DataHandler.php add the namespace:
use Smalot\PdfParser\Parser;
Now you are able to use the getPages() and getText() functions.
The Documentation
If i missed something let me know and i will add it.
Using DBIx::Class, I found a solution to my issue, thankfully. But I'm sure there has to be a nicer way.
my $record = $schema->resultset("food")->create({name=>"bacon"});
How would I turn this record into a simple hashref instead of having to make this call right after.
my record = $schema->resultset("food")->search({name=>"bacon"})->hashref_array();
Ideally I want to be able to write a code snippet as simple as
{record=> $record}
instead of
{record => {name => $record->name, $record->food_id, ...}}
This would drive me insane with a table that has alot more columns.
I assume you're talking about DBIx::Class?
my $record = $schema->resultset("food")->create({name=>"bacon"});
my %record_columns = $record->get_columns;
# or, to get a HashRef directly
my $cols = { $record->get_columns };
# or, as you've asked for
my $foo = { record => { $record->get_columns } };
What you're looking for is included in DBIx::Class as DBIx::Class::ResultClass::HashRefInflator.
I have large list of email addressses from a file. It comes around 1 million email ids. I have list of bad words like spam,junk etc, it consist of 20,000+ bad words.
I need to validate email ids. If bad words is present any where in email id it will be marked as invalid.
For example;
testspam#gmail.com - invalid
newuser#desspam.com - invalid
I would like to know which will be fastest comparison method as array looping will take time.
I tried following methods
//$keyword_list- array of bad words;
//$check_key- the email id which need to validate
$arrays = array_chunk($keyword_list, 2000);
for($i=0;$i<count($arrays);$i++)
{
if (preg_match('/'.implode('|', $arrays[$i]).'/', $check_key, $matches)){
return 1;
}
}
The above method is taking more time when comparing 1 million data.
Next we tried with the following code and this also takes more time
//$contain = bad words separated by '|'
// $str - the email id which need to validate
if(stripos($contain,"|") !== false)
{
$s = preg_split('/[|]+/i',$contain);
$len = sizeof($s);
for($i=0;$i < $len;$i++)
{
if(stripos($str,$s[$i]) !== false)
{
return(true);
}
}
}
if(stripos($str,$contain) !== false)
{
return(true);
}
return(false);
Finally I had tried Mongodb Text Search. It works fast with the following issues
If 'Hell' is the word in my bad list and my email id is like
head#e-hellinglysussex.sch.uk, then the Mongodb Text Search wont matches it.
Here is the code I used;
$ret = $db->command( array("text" =>$section, "search" => $keyword_string, "limit"=>$cnt_finalnonmatch));
where $section = Collection name,
$keyword_string = Comparing keywords string separated by space, for eg "Hell Spam Junk" etc,
$cnt_finalnonmatch = total number of comparing email ids
Please help me to solve this issue.
I am not entirely sure, but I suspect that the problem is that 'Hell' is not equal to 'hell' when you search for text since mongodb is case sensitive.
The solution should be to force all the strings and word to be lowercase (or uppercase)
We have used Mongodb 'like' to solve this issue;
$keywords = $key['keyword']; // Keywords need to compare
$regexObj = new MongoRegex("/".$keywords."/i"); // MongoRegex function declration
$where = array($section => $regexObj); // $section is the collection name
$resultset = $info->find($where);
After doing an insert I want to pass the object to the client using json_encode(). The problem is, the _id value is not included.
$widget = array('text' => 'Some text');
$this->mongo->db->insert($widget);
If I echo $widget['_id'] the string value gets displays on the screen, but I want to do something like this:
$widget['widgetId'] = $widget['_id']->id;
So I can do json_encode() and include the widget id:
echo json_encode($widget);
Believe this is what you're after.
$widget['_id']->{'$id'};
Something like this.
$widget = array('text' => 'Some text');
$this->mongo->db->insert($widget);
$widget['widgetId'] = $widget['_id']->{'$id'};
echo json_encode($widget);
You can also use:
(string)$widget['_id']
correct way is use ObjectId from MongoDB:
function getMongodbIDString($objectId){
$objectId = new \MongoDB\BSON\ObjectId($objectId);
return $objectId->jsonSerialize()['$oid'];
}
and do not cast the objectId like (string) $row['_id'] or $row->_id->{'$oid'}
I used something similar:
(string)$widget->_id
I used something similar if object:
$widget->_id->{'$oid'}
or
(string)$widget->_id
or array :
$widget['id']->{'$oid'}
(string)$widget['_id']
Can anyone tell me how to format the query below correctly in my controller.
Currently it gives me nothing in my FilteringSelect. However if I change it to >= I get back all the kennelIDs which is incorrect also but at least I'm getting something.
I've tested that the session variable is set and can confirm that there are kennels with the matching capacity.
// Create autocomplete selection for the service of this booking
public function servkennelAction()
{
$sessionKennelBooking = new Zend_Session_Namespace('sessionKennelBooking');
// disable layout and view rendering
$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender(true);
// get list of grooming services for dogs from the table
$qry= Doctrine_Query::create()
->from('PetManager_Model_Kennels k');
//This should be set by default and narrows down the search criteria
if(isset($sessionKennelBooking->numPets)){
$b=(int)$sessionKennelBooking->numPets;
$qry->addWhere('k.capacity = ?','$b');
}
$result=$qry->fetchArray();
//generate and return JSON string using the primary key of the table
$data = new Zend_Dojo_Data('kennelID',$result);
echo $data->toJson();
}
Many thanks in Advance.
Graham
I think that addWhere condition is wrong. It has to be:
$qry->addWhere('k.capacity = ?', $b);
i.e. $b without quotes.