hello community I don't know how to attach a pdf generated with tcpdf to a mail using the cakepdf plugin in cakephp 4 here my action of the controller that sends the mail
public function register()
{
$names = $doctor->name.' '.$doctor->last_name;
$dir = new Folder(WWW_ROOT.'register'.DS.$doctor->code_cmp, TRUE,0775);
//this function generates the pdf
$this->generatepdf($names,$doctor->specialty,$dir->path);
$email = new Mailer('blue-profile');
$email->setEmailFormat('html')
->setViewVars([
'names' => $names,
'specialty' => $doctor->specialty,
'user' => $doctor->code_cmp,
'password' => $this->request->getData('password')
])
->setFrom(['info#expertosaplv.pe' => 'Abbott'])
->setTo($doctor->email)
->setSubject('Bienvenido APLV Expertos Pediatras')
->viewBuilder()->setTemplate('welcome')->setLayout('default');
if($email->send()){
$message['success'] = "success";
echo json_encode($message);
die();
}
}
function that generates the pdf
public function generatepdf($names,$specialty,$dir)
{
$this->set(compact('names','specialty','dir'));
$this->viewBuilder()->setClassName('CakePdf.Pdf');
$this->viewBuilder()->setOptions([
'pdfConfig' => [
'margin' => [
'top' => 0,
'bottom' => 0,
'left' => 0,
'right'=> 0
],
'orientantion' => 'portrait',
'download' => false,
]
]);
}
here my template that from the pdf
require_once(ROOT.DS.'vendor'.DS.'tecnickcom'.DS.'tcpdf'.DS.'tcpdf.php');
require_once(ROOT.DS.'vendor'.DS.'tecnickcom'.DS.'tcpdf'.DS.'config'.DS.'tcpdf_config.php');
class PdfInvitation extends TCPDF{
public function Header() {
$bMargin = $this->getBreakMargin();
$auto_page_break = $this->AutoPageBreak;
$this->SetAutoPageBreak(false,0);
$this->SetAutoPageBreak($auto_page_break,$bMargin);
$this->setPageMark();
}
}
$img = WWW_ROOT.'img'.DS.'fond-pdf-notify.jpg';
$pdf = new PdfInvitation('P',PDF_UNIT,PDF_PAGE_FORMAT,TRUE,'UTF-8',FALSE);
////code pdf
$pdf->AddPage();
$pdf->lastPage();
$file = $pdf->Output('Diplomas-Eval-SER.pdf', 'S');
//I saw this code in the plugin documentation
$CakePdf = new \CakePdf\Pdf\CakePdf();
$CakePdf->template(DS.'Doctors'.DS.'pdf'.DS.'invitation','invitation');
$CakePdf->write($dir.DS.$file);
Maybe I'm doing something wrong, I would appreciate your help.
Related
I would like to know which of these 2 patterns would be better:
/photos/123/edit
or
/photos/edit/123
Currently I am using the first, which gives me a Whoops, looks like something went wrong. when I try /photos/123/editxx instead of a 404 not found.
routes:
I am unsure where to look for the mistake, these are the photos routes:
Route::get('photos/randpics','PhotosController#randpics');
Route::get('photos/{id}/edit','PhotosController#getEdit')->middleware(['auth']);
Route::post('photos/{id}/edit','PhotosController#postEdit')->middleware(['auth']);
Route::post('photos/{id}/retag', ['as' => 'photos.retag', 'uses' => 'PhotosController#retag'])->middleware(['auth']);
Route::post('photos/{id}/delete','PhotosController#delete')->middleware(['auth']);
Route::get('photos/{id}/albums', 'PhotosController#getAlbums')->middleware(['auth']);
Route::post('photos/{id}/albums', 'PhotosController#postAlbums')->middleware(['auth']);
Route::get('photos/{id}/detail','PhotosController#detail');
Route::get('photos/{id}','PhotosController#single');
Route::post('photos/like', 'PhotosController#postLike')->middleware(['auth']);
Route::post('photos/unlike', 'PhotosController#postUnlike')->middleware(['auth']);
Route::get('photos','PhotosController#index');
getEdit() and postEdit():
The same error, complaining about an undefined variable in the master layout template appears, when I enter /photos/123/a/a/a/ for example.
public function getEdit(Request $request, $id = null)
{
$pic = Pic::findOrFail($id);
if(Gate::denies('edit-pic',$pic)) {
abort(403);
}
$pic->text = htmlspecialchars($pic->text);
$years = array_combine(range(date("Y"), 1960), range(date("Y"), 1960));
$location = $pic->location;
$tags = $pic->tags;
$tagsarray = $pic->tagNames();
$albums = $pic->albums;
$locations = array();
$getlocations = Location::orderBy('city')->get();
foreach($getlocations as $gl)
{
$locations[$gl->id] = $gl->city.' ('.$gl->country.')';
}
$cats = Cat::lists('cat','cat')->all();
return view('photos.edit',compact('pic','location','tags','tagsarray','albums','locations','cats','years'));
}
public function postEdit(Request $request, $id = null)
{
$pic = Pic::findOrFail($id);
if(Gate::denies('edit-pic',$pic)) {
abort(403);
}
$this->validate($request, [
'title' => 'max:200',
'text' => 'max:3000',
'location' => 'required|exists:locations,id',
'cat' => 'required|exists:cats,cat',
'jahrprod' => 'date_format:Y'
]);
$pic->title = trim($request->input('title'));
$pic->text = trim($request->input('text'));
$pic->jahrprod = ($request->input('jahrprod')) ? $request->input('jahrprod') : null;
$pic->location_id = $request->input('location');
$pic->cat = $request->input('cat');
$pic->save();
#mail
$maildata = array(
'msg' => 'picture '.$id.' ( '.$request->input('title').' ) was edited by '.Auth::user()->username
);
Mail::send(['text' => 'emails.empty'], $maildata, function($message){
$message->to('xx#yy.de')->from('xx#yy.de')->subject('picture edited');
});
return back()->with('success','photo information updated');
}
Controller.php
It seems, with more than 2 URL segments, the Controller.php is not working properly. /domain.xy/1/2 shows the 8 but /domain.xy/1/2/3 throws the error Undefined variable: photos_online
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Auth;
use Cache;
use DB;
use App\Pic;
use App\Upload;
use Carbon\Carbon;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct()
{
dd(8);
//.......
}
}
If you follow laravel's resource controller guidelines
https://laravel.com/docs/5.2/controllers#restful-resource-controllers
You should go with the first one.
But to fix your problem show us your route and controller function handling it.
Update
open AppServiceProvider located in app/http/providers
and replace boot() function with this
public function boot()
{
//initilizw $photos_online
$photos_online = Cache::rememberForever('index_countpics', function()
{
return Pic::count();
});
#pics today
if (Cache::has('pics_today')){
$pics_today = Cache::get('pics_today');
}else{
$pics_today = Pic::whereRaw('DATE(created_at) = DATE(NOW())')->count();
Cache::put('pics_today', $pics_today, Carbon::tomorrow());
}
# count waiting uploads
$waiting_uploads = Cache::rememberForever('waiting_uploads', function()
{
return Upload::where('accepted',0)->where('infos',1)->count();
});
# user online
$client_ip = request()->ip();
$check = DB::table('useronline')->where('ip', $client_ip)->first();
$username = (Auth::guest()) ? null : Auth::user()->username;
$displayname = (Auth::guest()) ? null : Auth::user()->displayname;
if(is_null($check)){
DB::table('useronline')->insert(['ip' => $client_ip, 'datum' => DB::raw('NOW()'), 'username' => $username, 'displayname' => $displayname]);
}else{
DB::table('useronline')->where('ip', $client_ip)->update(['datum' => DB::raw('NOW()'), 'username' => $username, 'displayname' => $displayname]);
}
DB::delete('DELETE FROM useronline WHERE DATE_SUB(NOW(), INTERVAL 3 MINUTE) > datum');
$users_online = DB::table('useronline')->whereNotNull('username')->get();
$guests_online = DB::table('useronline')->count();
#unread messages
$unread_messages = 0;
if(Auth::check()){
$unread_messages = Auth::user()->newThreadsCount();
}
view()->share('photos_online',$photos_online);
view()->share('pics_today',$pics_today);
view()->share('waiting_uploads',$waiting_uploads);
view()->share('users_online',$users_online);
view()->share('guests_online',$guests_online);
view()->share('unread_messages',$unread_messages);
}
This is my controller.
public function actions()
{
return [
'auth' => [
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'oAuthSuccess'],
],
];
}
public function oAuthSuccess($client) {
$name = explode(" ",$userAttributes['name']);
$existing_customer = Customer::find()
->where(['email' => $userAttributes['email']])
->orWhere(['id_facebook' => $userAttributes['id']])
->one();
if(empty($existing_customer)){
$customer = new Customer();
$customer->firstname = $name[0];
$customer->lastname = $name[1];
$customer->id_default_group = 3;
$customer->username = $userAttributes['id'].'#facebook.com';
$customer->id_facebook = $userAttributes['id'];
$customer->email = $userAttributes['email'];
$password = rand(0000, 9999);
$auth_key = Yii::$app->getSecurity()->generateRandomString();
$customer->auth_key = $auth_key;
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);
$customer->password_hash = $hash;
$customer->activation_code = $password;
$customer->active =1;
if ($customer->save(false)) {
$customergroup = new CustomerGroup();
$customergroup->id_customer = $customer->id_customer;
$customergroup->id_group = $customer->id_default_group;
$customergroup->save(false);
Yii::$app->response->redirect(['advanced','email' => $customer->email]);
}
}
This is my main.php file.
'authClientCollection' => [
'class' => 'yii\authclient\Collection',
'clients' => [
'facebook' => [
'class' => 'yii\authclient\clients\Facebook',
'authUrl' => 'https://www.facebook.com/dialog/oauth?display=popup',
'clientId' => '',
'clientSecret' => '',
'scope' => [
'email',
'user_birthday',
'user_location',
'user_hometown',
],
],
],
],
Actually I am doing registration in 2 process.
After user click on facebook button it returns to my second step in popup, But i need it in my site. How is it possible?
change your auth successCallBack in action function with the action you desire..
below a sample where successCallback check if the user is a guest if true call the action authenticate otherwise the action connect
/** #inheritdoc */
public function actions()
{
return [
'auth' => [
'class' => AuthAction::className(),
'successCallback' => \Yii::$app->user->isGuest
? [$this, 'authenticate']
: [$this, 'connect'],
]
];
}
After the facebook login you return in your code inside the oAuthSuccess function .. i think the popup you are looking for is inside this function and is called from this redirect. if you want somethings others change the bootom part of this function..
Yii::$app->response->redirect(['advanced','email' => $customer->email]);
Can anyone suggest me how to hide both controller & action name from url in yii2?
I tried by writing rules but did not work.
this is my anchor tag:
<?php echo Html::a($model->title, ['category/view/', 'type' => $model->category->urlValue,'parameter' => $model->urlValue]); ?>
MY current url is like this :
http://localhost/project/category/view/news-and-events/dosarrest-strong-performer-in-2015-forrester-wave-for-ddos-service-providers-1
But I want it like this:
http://localhost/project/news-and-events/dosarrest-strong-performer-in-2015-forrester-wave-for-ddos-service-providers-1
It finally worked by writing a rule in main.php file as follows :
'<type:[A-Za-z0-9-]+>/<param:[A-Za-z0-9 -_.]+>' => 'category/view',
YOu chould create your own UrlRule. Something like:
class CustomUrlRule extends Object implements UrlRuleInterface {
public function createUrl($manager, $route, $params)
{
$parts = explode('/', $r);
if ($route === 'category/view'
&& isset($params['type'])
&& isset($params['parameter'])
) {
$url = generate some url;
unset($params['view'], $params['parameter']);
if (count($params)) {
$url .= '?' . http_build_query($params);
}
return $url;
}
return false;
}
public function parseRequest($manager, $request)
{
//parse request url and return true if it's url for category/view
}
}
and dont forget to add to config
config/web.php:
...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'app\components\CustomUrlRule',
],
...
],
...
I'm using ZfcUser in my app and I need to control the timeout parameter. As it's not part of the configuration I would like to set my own Zend/Session object (with the remember_me_seconds param) to ZfcUser on bootstrap but I don't know how.
By chance, has anyone done this already?
The easiest way to set session params is as follows
config\autoload\global.php
return array(
'service_manager' => [
'factories' => [
// Configures the default SessionManager instance
'Zend\Session\ManagerInterface' => 'Zend\Session\Service\SessionManagerFactory',
// Provides session configuration to SessionManagerFactory
'Zend\Session\Config\ConfigInterface' => 'Zend\Session\Service\SessionConfigFactory',
],
],
'session_manager' => [
// SessionManager config: validators, etc
],
'session_config' => [
'cache_expire' => 86400,
'cookie_lifetime' => 86400,
'remember_me_seconds' => 86400,
'gc_probability' => 10,
'gc_divisor' => 1000,
'use_cookies' => true,
'cookie_httponly' => true,
'cookie_lifetime' => 0, // to reset lifetime to maximum at every click
'gc_maxlifetime' => 86400,
],
);
And add line to onBootstrap method at Module.php
public function onBootstrap(MvcEvent $e)
{
$manager = $e->getApplication()->getServiceManager()->get('Zend\Session\ManagerInterface');
}
This will affect session setting and phpinfo() shows it.
I found it in zfcuser github
I don't use zfcuser but try this
autoload/global.php
<?php
use Zend\Session\Config\SessionConfig;
use Zend\Session\SessionManager;
use Zend\Session\Container;
return array(
'service_manager' => array(
'factories' => array(
'SessionManager' => function($sm) {
$sessionConfig = new SessionConfig();
$sessionConfig->setOption('remember_me_seconds', 1440);
$sessionManager = new SessionManager($sessionConfig);
Container::setDefaultManager($sessionManager);
return $sessionManager;
},
),
),
);
Module.php
public function onBootstrap($event)
{
$serviceManager = $event->getApplication()->getServiceManager();
$serviceManager->get('SessionManager')->start();
}
Here is how I did it. I am not the worlds greatest coder but this seems to work. This is all in Module.php
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$sharedManager = $eventManager->getSharedManager();
$sm = $e->getApplication()->getServiceManager();
//This checks to see if the user is logged in.
$eventManager->attach(MvcEvent::EVENT_DISPATCH, array($this, 'checkLogin'), 100);
}
//This function is attached to a listener to see if the user is not currently logged in
//If they are not logged in they will be redirected to the login page. This check will happen through the
//application so there is no need to keep checking in other modules
public function checkLogin (MvcEvent $e)
{
$session = new Container('defaults');
$this->route = $e->getRouteMatch();
$this->matchedRouteName = explode('/', $this->route->getMatchedRouteName());
$this->route_root = $this->matchedRouteName[0];
$sm = $e->getApplication()->getServiceManager();
$zfcServiceEvents = $sm->get('ZfcUser\Authentication\Adapter\AdapterChain')->getEventManager();
$zfcServiceEvents->attach(
'authenticate',
function ($e) use ($session) {
$session->offsetSet('sessionstart', $_SERVER['REQUEST_TIME']);
}
);
$auth = $sm->get('zfcuser_auth_service');
if (!$auth->hasIdentity() && $this->route_root != 'zfcuser')
{
$response = new \Zend\Http\PhpEnvironment\Response();
$response->getHeaders()->addHeaderLine('Location', '/user/login');
$response->setStatusCode(302);
$response->sendHeaders();
$e->stopPropagation(true);
return $response;
}
else if ($auth->hasIdentity() && $session->offsetGet('sessionstart') < ($_SERVER['REQUEST_TIME'] - 10800) && $this->route_root != 'zfcuser')
{
$response = new \Zend\Http\PhpEnvironment\Response();
$response->getHeaders()->addHeaderLine('Location', '/user/logout');
$response->setStatusCode(302);
$response->sendHeaders();
$e->stopPropagation(true);
return $response;
}
else if ($auth->hasIdentity())
{
$session->offsetSet('sessionstart', $_SERVER['REQUEST_TIME']);
}
}
My autocomplete is not working and I can't spot the error.
Jquery:
<script>
$(function() {
$('#autoComplete').autocomplete({
//source: "/groceries/items/autoComplete", ///This works but response isn't formatted correctly'
//dataType: "json"
minLength: 2,
source: function( request, response ) {
$.ajax({
url: "/groceries/items/autoComplete",
dataType: "jsonp",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
term: request.term
},
success: function( data ) {
response( $.map( data, function( el ) {
return { label: el.id, value: el.name }
}));
}
});
}
});
});
Controller:
public function autoComplete() {
Configure::write('debug', 0);
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
$this->set('items', $items);
}
Form:
<p>
<?php echo $this->Form->create('Item', array('model'=>'item','action' => 'addItem', 'name'=>'AddItem'));?>
<?php echo $this->Form->text('Item.name', array('size'=>'30', 'id'=>'autoComplete', 'autocomplete'=>'off')); ?>
<?php echo $this->Form->text('Item.category_id', array('type'=>'hidden', 'value'=>'0')); ?>
<?php echo $this->Form->text('Groclist.id', array('type'=>'hidden', 'value'=>$groclist['Groclist']['id'])); ?>
<?php echo $this->Form->end('Add'); ?>
</p>
Response:
0: {Item:{name:Cake, id:6, category_id:null}}
1: {Item:{name:Carrot Cake, id:9, category_id:null}}
2: {Item:{name:Carrots, id:8, category_id:null}}
3: {Item:{name:Casserole, id:11, category_id:null}}
4: {Item:{name:Cauliflower, id:10, category_id:null}}
Edited for clarification.
I realize JqueryUI expects label and value and that map should rearrange them, but for some reason it's not. Any ideas?
I found an even better solution. This is done completely in the controller. No view required.
public function autoComplete() {
Configure::write('debug', 0);
*$this->autoRender=false;*
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
*$i=0;
foreach($items as $item){
$response[$i]['value']="'".$item['Item']['id']."'";
$response[$i]['label']="'".$item['Item']['name']."'";
$i++;
}
echo json_encode($response);*
}
What if you reduce the array that is being returned by the Items model. So instead of $this->set('items', $items); you return the json encoded results like so:
foreach($items as $item) {
$data[] = $item['Item'];
}
$data = json_encode($data);
echo $data;
exit;
This is inside the auto_complete method in the controller.
UPDATE:
When querying for Cake for example, it would return a result like so:
[
{"name":"Cake Batter","id":"1","category_id":"3"},
{"name":"Cake Mix","id":"2","category_id":"3"}
]
if you are not wanting to return the json, you could just return $data without the json encoding.
Format Update:
I am not certain if this is to "sloppy", but you could change the foreach loop to:
foreach($items as $item) {
$data[]= array(
'label' => $item['Item']['name'],
'value' => $item['Item']['id']
);
}
Looks like you forgot the Item:
response($.map( data, function( el ) {
return { label: el.Item.id, value: el.Item.name }
});
You can also do it in the server side using Set:
$this->set('items', Set::extract('/Item', $items));