I want to show our users there Country Code, on the Product Page in our CS-Cart Store.
I have tried {$user_data.b_country} what didn't work.
Smarty Debug Console also does not show this information so I guess I have to assign this variable to the view.tpl File first.
How can I solve this problem?
You should probably try:
{$cart.user_data.b_country}
Before you call the variable on tpl you need to assign to array variable $user_data
b_country is part of a profile and the customer can have multiple profile
Script bellow will take the b_country from primary profile
1.
add file
app/addons/my_changes/init.php
with content
<?php
if (!defined('BOOTSTRAP')) { die('Access denied'); }
fn_register_hooks(
'sucess_user_login'
);
2.
add file
app/addons/my_changes/func.php
with content
<?php
if (!defined('BOOTSTRAP')) { die('Access denied'); }
function fn_my_changes_sucess_user_login(&$udata, $auth){
if(!isset($auth['b_country']) && $auth['user_id']>0){
$auth['b_country'] = db_get_field('SELECT b_country FROM `?:user_profiles` WHERE user_id = ?i AND profile_type = ?s', $auth['user_id'], 'P');
}
}
3.
now you can use in tpl
{$auth.b_country}
I hope that helps
Related
In order to reproduce a list of checkboxes like the one of the 'available carriers' in the Delivery section of the product page in the admin which allows to record the product-carrier associations, I ask for your help because I can't find how to retrieve the selected checkboxes to be able to use the setter of the association table ps_product_carrier defined in the product.php class
it would be in a JavaScript?
[Screen Admin Product page checkboxes list][1]
[1]: https://i.stack.imgur.com/4C79g.png
To get the carriers you need to use the getCarriers() function from the product class.
If the list is empty, all carriers are available. Therefore, if you want to display them you will need to use the Carrier::getCarriers() function to retrieve the list
If the list contains data, then that product has the specific carriers set.
So working directly on the front won't be enough as the variable is not loaded by default in the templates. What I would do is to create a micro-module with just the function to get that data.
Then you can use either a standard hook or create your own to display the data exactly where you want.
An example could be:
In the TPL add a custom hook call:
{hook h='displayProductCarriers' product=$product}
Then in your micro module:
public function hookDisplayProductCarriers($params)
{
if (isset($params['product'])) {
// Depending on the PS version product will be an array or an instance
if (is_array($params['product'])) {
$p = new Product((int)$params['product']['id_product']);
} elseif (is_object($params['product'])) {
$p = $params['product']);
}
$carriers = $p->getCarriers();
if (empty($carriers)) {
// Product has no specific carrier assigned
// Get all carriers here and assign them to smarty
$carriers = Carrier::getCarriers();
}
$this->context->smarty->assign('product_carriers', $carriers);
return $this->display(__FILE__, 'views/templates/hook/product-carriers.tpl');
}
}
That will allow the usage of the variable inside the template product-carriers.tpl there you can iterate through the {$product_carriers} variable and display whatever you need.
I am trying to make a product that will give me a different header based on the forum I am in, that's no problem and complete. My issue lays with using template conditionals inside of said option.
I am currently using a forum option to insert my custom template additions:
In global_complete hook I am using:
global $vbulletin;
if ($GLOBALS[foruminfo]["forumid"]>0) {
$forum_code = '';
$_fid = $GLOBALS[foruminfo]["forumid"];
$forum_info = $vbulletin->forumcache[$_fid];
if ($forum_info["code"]) {
$forum_code = $forum_info["code"];
} elseif ($forum_info["parentid"]) {
while ($forum_code=='' && $forum_info["parentid"]>0) {
$forum_info = $vbulletin->forumcache[$forum_info["parentid"]];
$forum_code = $forum_info["code"];
}
}
}
Then I place $forum_code into my header temple.
I would like to be able to get the conditionals to work so I can only show things to members or usergroups within the header. Is there a way to get the variable to not ignore the conditions? they are included in the DB entry, just being ignored when rendered to the page.
Sample Conditional:
<if condition="$show['member']">Member<else/>Guest</if>
What is actually being rendered:
MemberGuest
I have goggled a lot, but have not found a solution for my issue. The author of the widget references to the last answer of FAQ, but the FAQ does not have the answer or I cannot find it. I suppose it was updated since that time. Other fellows who faced the same issue and asked the same question just gone and did not provide any solution.
Anyway, in my case I have a table with button Pictures:
When a user clicks one of pictures button, modal dialog is shown. The user now can manage pictures for the chosen row. He can upload, delete pictures and so on. When the user opens the dialog for second row in the table he should see pictures for the second row only. It tells me that I have to clean the list of uploaded files every time user hits Pictures button to see the dialog. He will receive list of pictures which corresponds to chosen row from the server. Unfortunately, when I retrieve the list for the chosen row, the received files are added to the existing list.
Could you tell me how I can clean the list or reset the widget without removing files on the server side?
UPDATE I have used the following piece of code as a temporary solution.
jQuery.ajax({
url: "<YOUR URL HERE>",
dataType: 'json',
context: $('#fileupload')[0]
}).done(function (result) {
jQuery("#fileupload").find(".files").empty(); //this line solves the issue
jQuery(this).fileupload('option', 'done').call(this, null, { result: result });
});
Thank you.
i was also trying for one hour to get my upload work ;)
here is, how i solved this problem:
$('#html5FileInput').fileupload({
....
add: function (e, data) {
$.each(data.files, function (index, file) {
var newFileDiv = $(newfileDiv(file.name));
$('#fsUploadProgressHtml5').append(newFileDiv);
newFileDiv.find('a').bind('click', function (event) {
event.preventDefault();
var uploadFilesBox = $("#fsUploadProgressHtml5");
var remDiv = $(document.getElementById("fileDiv_" + event.data.filename));
removeFileFromArray(event.data.filename);
remDiv.remove();
data.files.length = 0;
...
});
data.context = newFileDiv;
});
...
)};
as you can see i create inside the add-event my file-dataset with 'newfileDiv(file.name)'. this creates a div with all information about the file (name, size, ...) and an ankor that exists for deleting the file from the list. on this ankor i bind a click-event in which i have the delete implementation.
hope this helps!
I know this isn't the most elegant solution, but I needed a very quick and dirty...so here's what I did (using jQuery).
//manually trigger the cancel button for all files...removes anything that isn't uploaded yet
$('.fileupload-buttonbar .cancel').first().trigger('click');
//check the checkbox that selects all files
if(!$('.fileupload-buttonbar .toggle').first().checked) {
$('.fileupload-buttonbar .toggle').first().trigger('click');
}
//manually trigger the delete button for all files
$('.fileupload-buttonbar .delete').first().trigger('click');
I know this isn't the best way. I know it isn't elegant...but it works for me and removes everything from the plugin.
If you have added file names or anything else from the plugin to any local arrays or objects, you'll need to clean those up manually (I have several handlers that fire on fileuploadadded, fileuploadsent, fileuploadcomplete, fileuploadfailed, and 'fileuploaddestroyed` events).
protected function get_file_objects($iteration_method = 'get_file_object') {
$upload_dir = $this->get_upload_path();
if (!is_dir($upload_dir)) {
return array();
}
return array_values(array_filter(array_map(
array($this, $iteration_method)
//scandir($upload_dir)
//File listing closed by Doss
)));
}
there is a scandir function responsible for listing the files. just uncomment it like i have done above and your problem is solved. it can be found in the UploadHandler.php file.
I need to render email templates in variable to send them later (which are stored in .phtml files), and i really don't want to implement my special class for handling this.
Is it possible to render not controller action view, but custom one?
I tried following code, but it outputs NULL :((
// Controller context
$view = new Phalcon\Mvc\View();
$view->setViewsDir('app/views/');
$view->setVar('var1', 'var2');
// Setting some vars...
$view->start();
$view->partial($emailTemplatePath);
$view->finish();
$result = $view->getContent();
var_dump($result); // Gives null
In addition to the response by Nikolaos, you can use $view->getRender() to render a single view returning its output.
$view->setViewsDir('apps/views/');
echo $view->getRender('partials', 'test'); // get apps/views/partials/test.phtml
You need to check the path of the $emailTemplatePath. It should point to the correct file i.e.
// points to app/views/partials/email.phtml
$view->partial('partials/email');
If you are using Volt and have registered that as your engine, then your file will need to be:
// app/views/partials/email.volt
I have a project where I use email and pdf templates and what I did was to have the rendering all take place within components.
Firstly, my folder structure contains (and I will only put here what is relevant) a cache, components and views directory. Let's look at the email setup rather than the PDF as this is more relevant to your situation.
/app
/cache
/email
/components
/views
/email
/elements
Of course there is public, controllers etc but let's not think about them for this.
I'm using Swift mailer for mine but I hope you will be able to use this all the same. In /app/components/Swift.php I have a __construct that calls for this->init_template_engine();
/**
* Create a volt templating engine for generating html
*/
private function init_template_engine() {
$this->_template = new \Phalcon\Mvc\View\Simple();
$di = new \Phalcon\DI\FactoryDefault();
$this->_template->setDI($di);
$this->_template->registerEngines([
'.volt' => function($view, $di) {
$volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di);
$volt->setOptions([
'compiledPath' => APP_DIR."cache".DS."email".DS, // render cache in /app/cache/email/
'compiledSeparator' => '_'
]);
return $volt;
// or use ".phtml" => 'Phalcon\Mvc\View\Engine\Php' if you want,
// both will accept PHP code if ya don't fancy it being a 100% volt.
},
]);
// tell it where your templates are
$this->_template->setViewsDir(APP_DIR.'views'.DS.'email'.DS);
return $this->_template;
}
The constants above (like APP_DIR) are something I have already made in my bootstrap and all they do is store full paths to directories.
Once the $_template variable has a template engine set up I can then use it to render my templates.
/**
* Returns HTML via Phalcon's volt engine.
* #param string $template_name
* #param array $data
*/
private function render_template($template_name = null, $data = null) {
// Check we have some data.
if (empty($data)) {
return false; // or set some default data maybe?
}
// Use the template name given to render the file in views/email
if(is_object($this->_template) && !empty($template_name)) {
return $this->_template->render($template_name, ['data' => $data]);
}
return false;
}
A sample volt email template may look like this:
{{ partial('elements/email_head') }}
<h2>Your Order has been dispatched</h2>
<p>Dear {{ data.name }}</p>
<p>Your order with ACME has now been dispatched and should be with you within a few days.</p>
<p>Do not hesitate to contact us should you have any questions when your waste of money arrives.</p>
<p>Thank you for choosing ACME Inc.</p>
{{ partial('elements/email_foot') }}
All I have to do then is grab the html and use swiftmailer's setBody method and I'm done:
->setBody($this->render_template($template, $data), 'text/html');
You don't need to place separate view engines like this in components, it could become memory hungry like that, but it does show the whole process. Hope that makes sense :)
The easiest way to render a view and return it as a variable is to use the Phalcon\Mvc\View\Simple class. In your controller, declare a new instance of the Simple view class and attach a rendering engine to it. You can then use its render() method to select a view file and pass in variables:
// create a simple view to help render sections of the page
$simple_view = new \Phalcon\Mvc\View\Simple();
$simple_view->setViewsDir( __DIR__ . '/../views/' );
$simple_view->setDI( $this->di );
$simple_view->registerEngines(array(
'.volt' => 'Phalcon\Mvc\View\Engine\Volt'
));
// use the simple view to generate one or more widgets
$widget_html = array();
$widget_objects = $widget_search->getWidgetObjects();
forEach( $widget_objects as $widget ){
$widget_html[] = $simple_view->render('index/widgetview',array('widget'=>$widget));
}
// pass the html snippets as a variable into your regular view
$this->view->setVar('widget_html',$widget_html);
use $view->render('partials/email') instead of calling partial method.
I usually use Volt engine and a simple way is a redefine view in DI container, like that:
$view = $this->view;
$content = $view->getRender('mail', 'show',
array(
"var1" => "some value 1",
"var2" => "some value 2"
),
function($view) {
$view->setRenderLevel(\Phalcon\Mvc\View::LEVEL_LAYOUT);
}
);
echo $content;
I am attempting to validate if a user, who belongs to a company, can view an item that belongs to a company...in other words, if they are an employee they should be able to view the company's items.
I'm trying to follow the example provided here:
http://www.yiiframework.com/doc/guide/1.1/en/topics.auth
This is the code I generated (run one time):
$auth=Yii::app()->authManager;
$auth->createOperation('viewItem','view an item');
$bizRule = 'return User::model()->findByPk(Yii::app()->user->getId())->company->id==$params["item"]->company->id';
$task=$auth->createTask('companyOwnedItem','view a company-owned item',$bizRule);
$task->addChild('viewItem');
This is the code in main.php:
'authManager'=>array(
'class'=>'CDbAuthManager',
'connectionID'=>'db',
This is the authorization piece used in my controller:
if (Yii::app()->user->checkAccess('companyOwnedItem',array('item'=>$item))) {
echo 'YES';
} else echo 'NO';
I always get 'NO' on the screen.
However if I use this code:
if (User::model()->findByPk(Yii::app()->user->getId())->company->id==$item->company->id)
Then I get 'YES' on the screen. What am I doing wrong and how do I use Yii's built-in authManager to make it work?
Best guess is that the item in items array isn't working properly. Have you turned on debugging for your auth manager? Forgot the property, but there is one to turn on in case of bizRule errors.
Other than that, it looks right. Also, FYI, after Yii 1.1.11, there is a $param['userId'] option so that you don't need to look up the current user's ID.
I ended up using the following and it worked:
In my config:
'authManager'=>array(
'class'=>'CDbAuthManager',
'connectionID'=>'db',
'defaultRoles'=>array('authenticated'),
'showErrors'=>true,
),
My authManager code:
$auth=Yii::app()->authManager;
$bizRule = 'return User::model()->findByPk(Yii::app()->user->getId())->company->id==$params["item"]->company->id;';
$auth->createOperation('companyOwnedItem','view a company-owned item',$bizRule);
$role = $auth->createRole('authenticated');
$role->addChild('companyOwnedItem');
Then in my controller:
if (Yii::app()->user->checkAccess('companyOwnedItem',array('item'=>$item))) {
echo 'YES';
} else {echo 'NO';}
And it works now!