I have a menu in my app:
<?php
NavBar::begin([
'brandLabel' => Html::img('#web/images/logo-top.png', ['id' => 'logo']),
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar-inverse navbar-static-top',
],
]);
if (count($menuItems)) {
echo Nav::widget([
'options' => ['class' => 'navbar-nav'],
'items' => $menuItems,
]);
}
?>
<?php NavBar::end(); ?>
$menuItems is generated within a Controller:
private function constructMenu($categories) {
$menu = [];
if (is_array($categories) && (count($categories) > 0)) {
foreach($categories as $key => $category) {
$menu[$key] = [
'label' => $category['name'],
'url' => Url::to([
'category/view',
'slug' => $category['slug']
]),
];
if (is_array($category['children']) && (count($category['children']) > 0)) {
$menu[$key]['items'] = $this->constructMenu($category['children']);
}
}
}
return $menu;
}
Also I have urlManager config:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'category/<slug:[\w_-]+>' => 'category/view',
'item/<slug:[\w_-]+>' => 'item/view',
'cart/remove/<item_id:\d+>' => 'cart/remove',
'cart/add/<item_id:\d+>' => 'cart/add',
],
],
So, the only problem is that the menu items are always active = false. How should I modify constructMenu method to set proper value for active key? Or maybe I should do it within the template?
Here is content of $menuItems from PhpStrom debug panel right before it will be passed to Nav::widget:
Here is where I am now:
NavBar::begin([
'brandLabel' => Html::img('#web/images/logo-top.png',
['id' => 'logo', 'style' => 'height: 40px; filter: invert(100%);']),
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar-inverse navbar-static-top',
],
]);
$controllerAndSlug = $this->context->id . '/' . $this->context->actionParams['slug'];
$menuItems = array_map(
function($item) use ($controllerAndSlug) {
$item['active'] = strpos($item['url'], $controllerAndSlug) !== false;
return $item;
},
$menuItems
);
if (count($menuItems)) {
echo Nav::widget([
'options' => ['class' => 'navbar-nav'],
'items' => $menuItems,
]);
}
NavBar::end();
It works fine, but sets active flag only on top level menu items. Now I wonder about how to pass a param to callback-function.
Although if you provide the full URL with /controller/action format it should work if it still does not, then you can use the active option of the item by checking the current controller, action, and slug
protected function constructMenu($categories) {
$menu = [];
$controller = Yii::$app->controller->id;
$action = Yii::$app->controller->action->id;
$slug = Yii::$app->request->get('slug');
if( is_array($categories) && (count($categories) > 0) ){
foreach( $categories as $key => $category ){
$isActive = ($controller == 'category' && $action == 'view' && $slug == $category['slug']);
$menu[$key] = [
'label' => $category['name'],
'url' => Url::to([
'category/view',
'slug' => $category['slug']
]),
'active' => $isActive
];
if( is_array($category['children']) && (count($category['children']) > 0) ){
$menu[$key]['items'] = $this->constructMenu($category['children']);
}
}
}
return $menu;
}
Try this:
private function constructMenu($categories) {
$menu = [];
if (is_array($categories) && (count($categories) > 0)) {
foreach($categories as $key => $category) {
$menu[$key] = [
'label' => $category['name'],
'url' => Url::to([
'category/view',
'slug' => $category['slug']
]),
'active' => Yii::$app->controller->id == 'category'
&& Yii::$app->controller->action->id == 'view'
&& Yii::$app->request->get('slug') == $category['slug']
];
if (is_array($category['children']) && (count($category['children']) > 0)) {
$menu[$key]['items'] = $this->constructMenu($category['children']);
}
}
}
return $menu;
}
Related
I am getting the below error. The PaymentIntent could not be captured because it has a status of requires_action. Only a PaymentIntent with one of the following statuses may be captured: requires_capture. This is my code to create a 3d secure payment gateway using stripe.
if ($this->paymentMethod == 'pay') {
$stripe = Stripe::make(env('STRIPE_SK'));
try {
$token = $stripe->tokens()->create([
'card' => [
'number' => $this->card_no,
'exp_month' => $this->exp_month,
'exp_year' => $this->exp_year,
'cvc' => $this->cvc,
]
]);
if (!isset($token['id'])) {
session()->flash('stripe_error', 'Token not generated');
$this->order_success = 0;
}
$customer = $stripe->customers()->create([
'name' => $this->fname.' '.$this->lname,
'email' => $this->email,
'phone' => $this->contact,
'address' => [
'line1' => $this->door_number.' '.$this->road_name,
'postal_code' => $this->post_code,
'state' => $this->address,
'city' => $this->city,
'country' => $this->country,
],
'shipping' => [
'name' => $this->fname.' '.$this->lname,
'phone' => $this->contact,
'address' => [
'line1' => $this->door_number.' '.$this->road_name,
'postal_code' => $this->post_code,
'state' => $this->address,
'city' => $this->city,
'country' => $this->country,
],
],
'source' => $token['id']
]);
$paymentIntent = $stripe->paymentIntents()->create([
'customer' => $customer['id'],
'currency' => 'GBP',
'amount' => session()->get('checkout')['total'],
'description' => 'Paid for Order No. '.$order->id,
'confirm' => true,
'capture_method' => 'automatic',
'confirmation_method' => 'automatic',
]);
$charge = $stripe->paymentIntents()->capture($paymentIntent['id']);
if ($paymentIntent['status'] == 'succeeded') {
$this->makeTransaction($order->id, 'approved');
$this->resetCart();
} else {
session()->flash('stripe_error', 'Payment not done');
$this->order_success = 0;
}
} catch (Exception $e) {
# code...
session()->flash('stripe_error', $e->getMessage());
$this->order_success = 0;
}
}
This is happening because you create the PaymentIntent and blindly capture it right after. Will your customer be on-session for the flow? If so, it will be easiest if you follow this guide/flow. You don't handle the case that the payment method will require auth for 3DS.
Can anyone help me in the implementation of nested set behavior https://github.com/creocoder/yii2-nested-sets with Yii2 Menu Widget?
Basically I want the hierarchical sidebar navigation menu like this http://www.surtex-instruments.co.uk/surgical/general-surgical-instruments
Thanks.
In your Model class define this functions:
public static function getTree($selected, $search)
{
$categories = Categories::find()->orderBy('lft')->asArray()->all();
$tree = [];
$index = 0;
foreach ($categories as $category) {
if ($category['parent_category_id'] === NULL) {
$tree[$index]['text'] = $category['category_' . Yii::$app->language];
if ($search) {
$tree[$index]['href'] = Url::to(['products', 'category' => $category['category_id'], 'search' => $search, 'string' => $category['category_' . Yii::$app->language]]);
} else {
$tree[$index]['href'] = Url::to(['products', 'category' => $category['category_id'], 'string' => $category['category_' . Yii::$app->language] ]);
}
$tree[$index]['id'] = $category['category_id'];
if ($selected) {
if ($selected['category_id'] == $category['category_id']) {
$tree[$index]['state']['selected'] = true;
}
if ($selected['lft'] >= $category['lft'] && $selected['rgt'] <= $category['rgt']) {
$tree[$index]['state']['expanded'] = true;
}
}
if ($category['lft'] + 1 != $category['rgt']) {
Categories::getNodes($tree[$index], $categories, $selected, $search);
}
$index++;
}
}
return $tree;
}
private static function getNodes(&$tree, $categories, $selected, $search)
{
$index = 0;
foreach ($categories as $category) {
if ($tree['id'] == $category['parent_category_id']) {
$tree['nodes'][$index]['text'] = $category['category_' . Yii::$app->language];
if ($search) {
$tree['nodes'][$index]['href'] = Url::to(['products', 'category' => $category['category_id'], 'search' => $search, 'string' => $category['category_' . Yii::$app->language]]);
} else {
$tree['nodes'][$index]['href'] = Url::to(['products', 'category' => $category['category_id'], 'string' => $category['category_' . Yii::$app->language]]);
}
$tree['nodes'][$index]['id'] = $category['category_id'];
if ($selected) {
if ($selected['category_id'] == $category['category_id']) {
$tree['nodes'][$index]['state']['selected'] = true;
}
if ($selected['lft'] >= $category['lft'] && $selected['rgt'] <= $category['rgt']) {
$tree['nodes'][$index]['state']['expanded'] = true;
}
}
if ($category['lft'] + 1 != $category['rgt']) {
Categories::getNodes($tree['nodes'][$index], $categories, $selected, $search);
}
$index++;
}
}
}
and use this extension execut/yii2-widget-bootstraptreeview
In the controller file get the menu like this:
public function actionProducts($category = false)
{
...
$data = Categories::getTree($category,'');
In your view file
<?php
...
use execut\widget\TreeView;
...
$onSelect = new JsExpression(<<<JS
function (undefined, item) {
window.location.href = item.href;
}
JS
);
?>
<?= TreeView::widget([
'data' => $data,
'template' => TreeView::TEMPLATE_SIMPLE,
'clientOptions' => [
'onNodeSelected' => $onSelect,
'onhoverColor' => "#fff",
'enableLinks' => true,
'borderColor' => '#fff',
'collapseIcon' => 'fa fa-angle-down',
'expandIcon' => 'fa fa-angle-right',
'levels' => 1,
'selectedBackColor' => '#fff',
'selectedColor' => '#2eaadc',
],
]); ?>
$a = array(array( 'dates' => '12-11-13',
'customer' => 'ann',
'place' => 'EKM'),array('dates' => '12-11-13',
'customer' => 'annex',
'place' => 'KLM'),array('dates' => '13-11-13',
'customer' => 'anna',
'place' => 'PTA')
);
how to this array displayed following format using PHP
dates:12-11-13
customer:ann
place:EKM
customer:annex
place:KLM
dates:13-11-13
customer:anna
place:PTA
Something like this:
$a = array(array( 'dates' => '12-11-13',
'customer' => 'ann',
'place' => 'EKM'),array('dates' => '12-11-13',
'customer' => 'annex',
'place' => 'KLM'),array('dates' => '13-11-13',
'customer' => 'anna',
'place' => 'PTA')
);
foreach ($a as $row) {
foreach ($row as $k => $v) {
echo "$k:$v<br/>";
}
echo "<br/>";
}
<?php
$a = array(array( 'dates' => '12-11-13',
'customer' => 'ann',
'place' => 'EKM'),array('dates' => '12-11-13',
'customer' => 'annex',
'place' => 'KLM'),array('dates' => '13-11-13',
'customer' => 'anna',
'place' => 'PTA')
);
$result = array(); //Your minimized array
foreach($a as $value)
{
$dates = $value['dates'];
if(isset($result[$dates]))
$index = ((count($result[$dates]) - 1) / 2) + 1;
else
$index = 1;
$result[$dates]['dates'] = $dates;
$result[$dates]['customer' . $index] = $value['customer'];
$result[$dates]['place' . $index] = $value['place'];
}
$result = array_values($result);
for($i=0;$i<count($result);$i++)
{
foreach($result[$i] as $r1)
{
$r2[$i][]=$r1;
}
?>
<?php echo 'dates:'.$r2[$i][0].'</br>';?>
<?php
if(count($r2[$i])>3)
{
?>
<?php
$k=count($r2[$i]);
for($j=1;$j<$k;$j++)
{
?>
<?php echo 'customer:'.$r2[$i][$j].'</br>';?>
<?php echo 'place:'.$r2[$i][$j+1].'</br>';?>
</tr>
<?php
$j=$j+1;
}
echo '</br>';
}
else
{
?>
<?php echo 'customer:'. $r2[$i][1].'</br>';?>
<?php echo 'place:'.$r2[$i][2].'</br></br>';?>
<?php
}
}
?>
Is it possible to create a module that outputs two tabs into the publish screen, or do I have two create another module to to create my second tab or just another tab.file.php file?
CODE
FILE: upd.my_module.php
class My_module_upd {
var $version = '1.0';
public function __construct(){
$this->EE =& get_instance();
}
public function install(){
$this->EE->load->dbforge();
$data = array(
'module_name' => 'My Module',
'module_version' => $this->version,
'has_cp_backend' => 'y',
'has_publish_fields' => 'y'
);
$this->EE->db->insert('modules', $data);
return true;
}
public function tabs(){
$tabs['tab_1'] = array(
'field_1' => array(
'visible' => TRUE,
'collapse' => FALSE,
'htmlbuttons' => TRUE,
'width' => '100%'
),
'field_2' => array(
'visible' => TRUE,
'collapse' => FALSE,
'htmlbuttons' => TRUE,
'width' => '100%'
)
);
$tabs['tab_2'] = array(
'field_1' => array(
'visible' => TRUE,
'collapse' => FALSE,
'htmlbuttons' => TRUE,
'width' => '100%'
),
);
return $tabs;
}
}
FILE: tab.my_module.php
class My_module_tab {
public function __construct(){
$this->EE =& get_instance();
}
public function publish_tabs($channel_id, $entry_id = ''){
$settings = array(
'field_1' => array(
'field_id' => 'field_1',
'field_label' => 'Field 1',
'field_type' => 'text',
'field_required' => 'n',
'field_data' => '',
'field_text_direction' => 'ltr',
'field_maxl' => 100,
'field_instructions' => '',
),
'field_2' => array(
'field_id' => 'field_2',
'field_label' => 'Field 2',
'field_type' => 'text',
'field_required' => 'n',
'field_data' => '',
'field_text_direction' => 'ltr',
'field_maxl' => 100,
'field_instructions' => '',
),
);
return $settings;
}
}
In the My_module_upd->tabs() method it looks like to can declare multiple tabs in the array but the My_module_tab class seems geared to controlling just one tab. Can anyone point me in the right direction?
I am trying to create a simple module in Drupal 6.20 as follows:
<?php
function example_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('This module implements an example form.');
}
}
function example_menu($may_cache) {
$items = array();
if ($may_cache)
{
$items[] = array(
'path' => 'example',
'title' => t('Example'),
'callback' => 'example_page',
'access' => TRUE,
'type' => MENU_NORMAL_ITEM
);
}
return $items;
}
function example_page() {
return drupal_get_form('example_page_form');
}
function example_page_form() {
$form['fullname'] = array(
'#type' => 'textfield',
'#title' => t('Enter your full name'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
function example_page_form_submit($form_id, $form_values) {
...some code
}
But whenever i am typing in http://mysite.com/example, its getting redirected to 404. Please help. I am very new to Drupal technology. Is there ne more files needed for this apart from the .info and .module file?
Thanks.
Ive got the solution. For Drupal 6.X it menu hook should be as follows:
function example_menu() {
$items = array();
$items['example'] = array(
'title' => 'List',
'page callback' => 'example_page',
'access callback' => 'user_access',
'access arguments' => array('access content'),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
return $items;
}