wkhtmltopdf Import font rendering image instead of text - wkhtmltopdf

I would like to use custom fonts with wkhtmltopdf and render my pdf with police integrated to it.
My customs fonts are "Biondy regular" and "Century Gothic". I bought them from "myfonts".
Throught a Symfony 3.4 application, I launch the generation of the PDF with somes parameters and CSS.
/**
* Generate a PdfResponse.
*
* #param string $render
* #param string $view
* #param string $outputFileName
* #param int $margin
* #return PdfResponse
*/
public function generate(string $render, string $view, string $outputFileName, int $margin = 0): PdfResponse
{
$options = [
'user-style-sheet' => [
'dir_to_my_css_file.css',
],
'margin-top' => $margin,
'margin-bottom' => $margin,
'margin-left' => $margin,
'margin-right' => $margin,
'page-size' => 'A4',
];
$pdf = $this->snappy->getOutputFromHtml($view, $options);
return new PdfResponse($pdf, $outputFileName, 'application/pdf');
}
My PDF is well generated whith all the CSS and fonts. But it's an image not text.
If i remove my customs fonts, PDF is generated with text, not image.
To resolve the problem, I think I have to export my police to the PDF but I didn't found how to make that.
Thanks for your time.

To solve my problem, I installed fonts on my server.
It seems wkhtmltopdf use systems fonts for generation.
If fonts are not found, a pdf image is generated else it generate a pdf text.

Related

Unable to post data

Hello, it is a very important project for me. I wrote an api and I want to pull data from 2 different sites with this api. While you can pull healthy data from one site, empty results are returned due to captcha from the other site. Now I scraped data from the same site before using pyhton selenium, bs4, but I can't scrape it with laravel api. I'm testing this info from postman.
The solution of the captcha is to combine my pyhton file, which I have provided, with my laravel api file, if possible, by converting the captcha to audio and then to text, which skips this part.
Another method is to write a pyhton service that can work with the captcha(pyhton) file.
The last and actually the most useful method for me if I can provide action is to skip captcha with my laravel service without entering the captcha event. I tried skipping by changing the cookie, but it was a very tiring and unhealthy method. I want to trick some kind of captcha here.
<?php
namespace App\Services\Mde;
use App\Core\ServiceResponse;
use App\Interfaces\IPricePredictionService;
class PricePredictionService extends BaseMDeService implements IPricePredictionService
{
/**
* #param mixed $brand
* #param mixed $model
* #param mixed $kilometerFrom
* #param mixed $kilometerTo
* #param mixed $yearFrom
* #param mixed $yearTo
* #param mixed $fuelTypes
* #param mixed $gearBoxes
* #param mixed $powerFrom
* #param mixed $powerTo
*
* #return ServiceResponse
*/
public function getByParameters(
$brand,
$model,
$kilometerFrom,
$kilometerTo,
$yearFrom,
$yearTo,
$fuelTypes,
$gearBoxes,
$powerFrom,
$powerTo
): ServiceResponse
{
$endpoint = $this->baseUrl . '&ms=' . $brand . '%3B' . $model;
$priceList = [];
for ($pageCounter = 1; $pageCounter <= 50; $pageCounter++) {
$parameters = [
'ml' => $kilometerFrom,
'ml%3A' => $kilometerTo, // duzelt
'fr' => $yearFrom, // duzelt
'fr%3A' => $yearTo, // duzelt
'fuel' => implode(' ', $fuelTypes), //ft=DIESEL
'gear' => implode(' ', $gearBoxes), //tr=MANUAL_GEAR
'powertype' => 'kw',
'pw' => $powerFrom, // duzelt
'pw%3A' => $powerTo, // duzelt
'page' => $pageCounter,
];
$response = $this->client->get($endpoint . '?' . http_build_query($parameters), [
'headers' => [
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
//'Accept' => 'application/json',
'Accept-Encoding' => 'gzip, deflate, br',
'Accept-Language' => 'tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7',
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36' //,
],
]);
$clean1 = str_replace(["\n", "\t", "\r", " "], null, $response->getBody()->getContents());
$clean2 = str_replace(["""], null, $clean1);
$clean3 = preg_replace('~{(.*?)}~', null, $clean2);
$cleanResult = preg_replace('~{(.*?)}~', null, $clean3);
preg_match_all('~<a class="link--muted no--text--decoration result-item" (.*?)</a>~', $cleanResult, $articles);
//return $lists; // bos geliyor.
if ($articles[1]) {
foreach ($articles[1] as $article) {
preg_match('~<span class="h3 u-block" .*?>(.*?)</p>~', $article, $priceObject);
$priceWithCurrency = str_replace(',-', null, $priceObject[1]);
$priceWithoutCurrency = explode(' ', $priceWithCurrency)[1];
$price = intval(str_replace('.', null, $priceWithoutCurrency));
$priceList[] = $price;
}
}
}
$averagePrice = array_sum($priceList) / count($priceList);
return new ServiceResponse(
true,
'Average price calculated successfully.',
200,
intval($averagePrice)
);
}
}
I don't insist that these methods are just the ones that come to my mind, I want to proceed in this way, I just want to provide fast and practical transactions whenever possible. I'm sorry if I said something illogical and wrong. But I desperately need the ideas and guidance you will convey to me. Thank you from now. I'm also adding my api codes in case you want to take a look.
The controller class is below.
```
<?php
namespace App\Http\Controllers\Api\M;
use App\Core\Controller;
use App\Core\HttpResponse;
use App\Http\Requests\Api\M\PricePredictionController\CheckRequest;
use App\Interfaces\IPricePredictionService_M;
class PricePredictionController extends Controller
{
use HttpResponse;
/**
* #var $mService
*/
private $mService;
public function __construct(IPricePredictionService_M $mService)
{
$this->mService = $mService;
}
/**
* #param CheckRequest $request
*/
public function check(CheckRequest $request)
{
$response = $this->mService->getByParameters(
$request->brand_and_model,
$request->kilometerFrom_kilometerTo,
$request->yearFrom_yearTo,
$request->fuelTypes ?? [],
$request->gearBoxes ?? [],
$request->powerFrom_powerTo,
$request->country,
$request->bodyType,
$request->doors
);
return $this->httpResponse(
$response->getMessage(),
$response->getStatusCode(),
$response->getData(),
$response->isSuccess()
);
}
}
> The interfaces class is below.
```
<?php
namespace App\Interfaces;
use App\Core\ServiceResponse;
interface IPricePredictionService_M
{
/**
* #param mixed $brand_and_model
* #param $kilometerFrom_kilometerTo
* #param mixed $yearFrom_yearTo
* #param mixed $fuelTypes
* #param mixed $gearBoxes
* #param mixed $powerFrom_powerTo
* #param mixed $country
* #param mixed $bodyType
* #param mixed $doors
*
* #return ServiceResponse
*/
public function getByParameters(
$brand_and_model,
$kilometerFrom_kilometerTo,
$yearFrom_yearTo,
$fuelTypes,
$gearBoxes,
$powerFrom_powerTo,
$country,
$bodyType,
$doors
): ServiceResponse;
}

How to embed base64 images in a Laravel markdown email

I have an automated email in Laravel PHP which informs the user that a particular product has expired.
I would like to include a base64 image which should be embedded within the email itself.
Is it possible to embed base64 images in a markdown email with Laravel?
If so how?
The following is the email markdown blade template:
#component('mail::message')
![Logo][logo]
[logo]: {{asset('frontend/img/core-img/logo-dark.png')}} "Logo"
**Product Expiry**
Dear {{$userName}},
This is to inform you that your product **{{$listingName}}**.
Your item was removed from the Market Place. Should you wish to re-list the item kindly do so from the app.
![alt]{{$listingImage}}
Should you require any information or need professional assistance kindly get in touch:
#component('mail::button', ['url' => ''])
Contact Us
#endcomponent
Thanks,<br>
# **{{ config('app.name') }} Team**
![App Icon|100x100]({{asset('frontend/img/core-img/app-logo.png')}})
#endcomponent
and the is the class for this email template:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ListingExpiryEmail extends Mailable
{
use Queueable, SerializesModels;
protected $user_name;
protected $listing_name;
protected $listing_image;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($user_name, $listing_name, $image)
{
$this->user_name = $user_name;
$this->listing_name = $listing_name;
$this->listing_image = $image;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('MyHurryApp Listing Expiry')->markdown('emails.listings.listingexpiryemail', [
'userName' => $this->user_name,
'listingName' => $this->listing_name,
'listingImage' => $this->listing_image
]);
}
}
Thanks
This works for me
<img src="data:image/png;base64,{{base64_encode(file_get_contents(public_path('/image/logo.png')))}}">
After further research I found out that this is not possible.
As per: https://superuser.com/questions/1199393/is-it-possible-to-directly-embed-an-image-into-a-markdown-document
Markdown documents is just a text file and text editors would not know what to do with a binary image within the "text".
Having said that there might be a way around this limitation:
There are methods like MIME and base64 to encode binary data into a text file in a sense, but most text editors and Markdown-renderers wouldn't know what to do with a MIME encoded document that contains a Markdown text part and a base64 encoded image part.
But I am still looking into a possible solution.
If someone can guide me further would be highly appreciated.
Thanks

Intervention\Image\Exception\NotSupportedException Encoding format (tmp) is not supported

I am using the Intervention package with Laravel 5.6, the issue I am getting whenever I am uploading a file I have been presented with the error Encoding format(tmp) is not supported. I have my gdd2 extension enabled also. This is the code where I have used.
public function store(Request $request)
{
$this->validate($request , [
'name' => 'required|unique:categories',
'description' => 'max:355',
'image' => 'required|image|mimes:jpeg,bmp,png,jpg'
]);
// Get Form Image
$image = $request->file('image');
$slug = str_slug($request->name);
if (isset($image))
{
$currentDate = Carbon::now()->toDateString();
$imageName = $slug.'-'.$currentDate.'-'.uniqid().'.'.$image->getClientOriginalExtension();
// Check if Category Dir exists
if (!Storage::disk('public')->exists('category'))
{
Storage::disk('public')->makeDirectory('category');
}
// Resize image for category and upload
$categoryImage = Image::make($image)->resize(1600,479)->save();
Storage::disk('public')->put('category/'.$imageName, $categoryImage);
// Check if Category Slider Dir exists
if (!Storage::disk('public')->exists('category/slider'))
{
Storage::disk('public')->makeDirectory('category/slider');
}
// Resize image for category slider and upload
$categorySlider = Image::make($image)->resize(500,333)->save();
Storage::disk('public')->put('category/slider/'.$imageName, $categorySlider);
}
else
{
$imageName = 'default.png';
}
$category = new Category();
$category->name = $request->name;
$category->slug = $slug;
$category->description = $request->description;
$category->image = $imageName;
$category->save();
Toastr::success('Category Saved Successfully','Success');
return redirect()->route('admin.category.index');
}
You don't need to use the save() function on the Intervention\Image class as you are saving the file to your public disc via the Storage Facade.
Simply replace the line
$categoryImage = Image::make($image)->resize(1600,479)->save();
with
$categoryImage = Image::make($image)->resize(1600,479)->stream();
to avoid having to store the image to the temp folder under a .tmp extension. Laravel Storage Facade will handle the stream created by Intervention\Image and store the file to the public disk.
The Intervention image save() method requires a filename so it knows what file format (jpg, png, etc..) to save your image in.
The reason you are getting the error is it does not know what encoding to save the temporary image object (tmp) in.
Here is an example
->save('my-image.jpg', 90)
There is also a optional second parameter that controls the quality output. The above outputs at 90% quality.
http://image.intervention.io/api/save
Saw this somewhere and it worked for me
$image->save('foo' . $img->getClientOriginalExtension());
The Laravel Intervention image save() method requires a filename so it knows what file format (jpg, png, etc..) to save your image in
$categoryImage = Image::make($image)->resize(1600,479)->save( $imageName,90);
I've solved this by
Trimming
my file path, i was using this script inside laravel Artisan Console.
$img->save(trim('public/uploads/images/thumbnails/'.$subFolder.'/'.$filename));
Rather you use stream its working without error
$categoryImage = Image::make($image)->resize(1600,479)->save();
$categoryImage = Image::make($image)->resize(1600,479)->save();
Storage::disk('public')->put('category/'.$imageName, $categoryImage);
change to
Image::make($image)->resize(1600, 479)->save(storage_path('app/public/category').'/'.$imagename);
$categorySlider = Image::make($image)->resize(500,333)->save();
Storage::disk('public')->put('category/slider/'.$imageName, $categorySlider);
change to
Image::make($image)->resize(500, 333)->save(storage_path('app/public/category/slider/') .$imagename);

Add module to subpage in Joomla

I have a module which I add from admin panel to some subpage. After that some subpages show properly content with this module but some subpages after click on it open blank, white page with no content inside. I don't know what caused that problem. Why some subpages with this module work properly and some show blank page?
This is what I see on page:
Fatal error: Cannot redeclare class ModProductsMenuHelper in /opt2/data-dev/modules/mod_products_menu/helper.php on line 15
Thank you for help!
This is my code
<?php
/**
* Slajder class for Hello World! module
*
* #package Joomla.Tutorials
* #subpackage Modules
* #link http://docs.joomla.org/J3.x:Creating_a_simple_module/Developing_a_Basic_Module
* #license GNU/GPL, see LICENSE.php
* mod_helloworld is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
*/
class ModProductsMenuHelper
{
/**
* Retrieves the hello message
*
* #param array $params An object containing the module parameters
*
* #access public
*/
public function getProducts($params)
{
$lang = JFactory::getLanguage();
$langTag = $lang->getTag();
$app = JFactory::getApplication();
$isSMB = $app->get('isSMB');
$parentMenuId = $langTag == 'pl-PL' ? 107 : 103;
$results = $this->getChildren($parentMenuId, $langTag);
return $results;
}
private function getChildren($parentId, $langTag){
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
$query
->select(array('id', 'title', 'path', 'alias'))
->from($db->quoteName('#__menu'))
->where("(language = '*' OR language= ".$db->quote($langTag).") AND published = 1 AND parent_id=".$parentId)
->order($db->quoteName('lft') . ' ASC, '.$db->quoteName('id') . ' ASC');
// Reset the query using our newly populated query object.
$db->setQuery($query);
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$results = $db->loadObjectList();
foreach ($results as $key=>$val){
$results[$key]->children = $this->getChildren($val->id, $langTag);
}
return $results;
}
}
From what I can gather you have created a module and assigned it to specific pages. You haven't mentioned what the contents of the module are (custom html etc).
Have you assigned the module to the correct pages in the 'module assignment' tab? Have a look at this question and answer as it explains how to do that.
If you are seeing a white page, i'd suggest enabling error reporting in Joomla. This should provide you with additional useful information about the error.
If you have a link to your website that would be helpful, and the version of Joomla you are using.

Symfony2 validate text input when containing something only

I want to validate a form which holds a dropdown menu and a text input field.
The user can choose a project from the dropdown menu. If he wants to create a new project he can use the text input field next to the dropdown menu.
Here is my upload type:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction('upload')
->setMethod('POST')
// project name dropdown menu
->add('projectname', 'choice' , array(
'label' => 'upload_project_label',
'choices' => $this->projects,
'attr' => array(
'class' => 'form-control some',
'required' => 'true'
)
))
// newprojectname text input
->add('newprojectname', 'text', array(
'label' => false,
'attr' => array(
'class' => 'form-control',
'required' => false,
'placeholder' => 'upload_newprojectname_placeholder'
)
)
)
...
And this is a snippet from my upload entity:
/**
* #ORM\Column(type="text")
*
* #var string $projectname
* #Assert\NotBlank()
*/
protected $projectname;
/**
* #ORM\Column(type="text")
*
* #var string $newprojectname
* #Assert\Length(
* min = 3,
* max = 7,
* minMessage = "min message",
* maxMessage = "max message"
* )
*/
protected $newprojectname;
My question is is there a possibility of a query to check if the field newproject is set (i.e. a string is entered)? And if so let the Assert annotation do its job.
This can be done a number of ways, all of which will likely satisfy your requirements.
Use a custom callback - this is the quickest and most straightforward
Use an expression validator - a lot of people have issues with embedding a meta-language within PHP which is perfectly valid but this is another quick-ish way of doing things
Use group sequences, specifically the group sequence provider functionality
Which one you choose is up to you but callbacks are a quick and easy starting point that you can build on if your validation constraints become more complex.
This is the code block for advised solution as custom callback validation.
I had to add another function in my upload entity which looks like this:
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* Function holds custom validation for fields in import/upload form
* #Assert\Callback
* #param ExecutionContextInterface $context
*/
public function validate(ExecutionContextInterface $context)
{
// check new project name
$newProjectName = $this->getNewprojectname();
if(!empty($newProjectName)) {
// letters only
$pattern = '/[a-zA-Z]/';
if($this->isPatternWrong($newProjectName, $pattern)) {
$context
->buildViolation('Please use letters only.')
->atPath('newprojectname')
->addViolation();
}
// text max. 7 digits
$maxlength = 7;
if($this->isStringTooLong($newProjectName, $maxlength)) {
$context
->buildViolation('Max. length 7 digits.')
->atPath('newprojectname')
->addViolation();
}
}
}
private function isPatternWrong($string, $pattern)
{
$result = preg_match($pattern, $string);
if($result === 0) {
return true;
}
return false;
}
private function isStringTooLong($string, $length)
{
if(strlen($string) > $length) {
return true;
}
return false;
}

Resources