For SEO purposes I need to remove the first page number from the URL. i.e I have the following:
example.com/pages/view/1 and example.com/pages/view the two URLs points to the same contents of the view action. I want to make the pagination free from 1 in the URL. i.e first Page link and Page Number 1 should be linked to pages/view.
I tried to deal with the $pagination object like the following:
$pages = new Pagination(['totalCount' => $books['booksCount'], 'pageParam' => 'start', 'defaultPageSize' => 10,]);
$pagingLinks = $pages->getLinks();
$pagingLinks['first'] = '/';
$pages->links = $pagingLinks;
However, the last line causing error:
Setting read-only property: yii\data\Pagination::links
So I have a problem to modify the links property. Is there any other solution to get this task done?!
According to docs you should set yii\data\Pagination::forcePageParam to false by passing it in Pagination constructor
$pages = new Pagination([
'totalCount' => $books['booksCount'],
'pageParam' => 'start',
'defaultPageSize' => 10,
'forcePageParam' => false,
]);
The above answer may works for direct use of Pagination but remain an issue if it was used from another widget such as ListView.
I found the solution from a comment on an issue report on Yii2 repository on github
The solution is just define proper route in config/web.php. Suppose here we have a controller called Suras and we use the ListView widget on its action's view called view. So placing rule array with defaults has value 'page' => 1 will prevent adding the page parameter to the link's URL of the first page. Also notice the first rule 'view/<id:\d+>/1' => 'Error404', is placed in-order to prevent any access to the first page using page=1 parameter, for example, trying to access mysite.com/view/20/1 will invoke 404 error, because there is no controller called Error404.
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'view/<id:\d+>/1' => 'Error404',
['pattern' => 'view/<id:\d+>/<page:\d+>', 'route' => 'suras/view', 'defaults' => ['page' => 1]],
'view/<id:\d+>/<page:\d+>' => 'suras/view',
'view/<id:\d+>' => 'suras/view',
],
],
],
Related
In Data Objects we have the possibility to render multiselects as tags. Is it possible to achieve the same functionality in documents?
We have tried the following but nothing seems to change:
<?= $this->multiselect($filter, [
"width" => 200,
"height" => 150,
'renderType' => 'tags',
"store" => \InteliveBundle\Model\Utils::getSelectOptions($filter),
"reload" => false,
'class' => "editmode-cssid",
'htmlspecialchars' => false,
]); ?>
According to the documentation you have the following configuration options:
store array Key/Value pairs for the available options.
width integer Width of a generated block in editmode
height integer Height of a generated block in editmode
class string A CSS class that is added to the surrounding container
of this element in editmode
https://pimcore.com/docs/6.x/Development_Documentation/Documents/Editables/Multiselect.html
Therefore this feature seems not to be implemented. You can make a feature request in https://github.com/pimcore/pimcore or even better you fork the project, implement this feature and make a merge request.
I am using Yii2 with Pjax for index/gridview listing. using pjax pagination , search all working fine without postback to server.
My problem starts now,
suppose i am on page number 2, i have clicked on edit record of that 2nd page list, i reach to update view, i have done changes and saved, now i am redirected to view , now i clicked on index link from breadcrumbs.
i want to reach to page number 2 of index rather then 1st page.
Traditional process for this is get refereeing page params an append that in breadcrumbs.
But is there any simple approach to this problem where i can write few lines of code and its applied to every where in backend?
Thanks for reading.
For remembering grid filter, pages i use yii2-grid-view-state
If you need to store page only, isn't it quite easy to pass page param into your view url (<model/view>) like <model>/view?id=<id>&page=<page>?
in your index.php view, edit your ActionColumn as follow:
[
'class' => 'yii\grid\ActionColumn',
'urlCreator' => function ($action, $model, $key, $index) {
return \yii\helpers\Url::to([$action, 'id' => $model->id, 'page' => Yii::$app->request->getQueryParam('page', null)]);
},
],
As you can see, I'm getting page param from request url and pass it to models' action buttons (to all buttons, but in your question it would be enough for view button of course)
And when you click to view model, in our Controller we need to get that page value and pass it to our view.php view (in order to place it in breadcrumbs).
Our ModelController:
public function actionView($id, $page = null)
{
return $this->render('view', [
'model' => $this->findModel($id),
'page' => $page,
]);
}
And finally view.php view will get the page value, and populate the index url (if not null):
/* #var $page int */
$this->title = $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Index', 'url' => ['index', 'page' => $page]];
So when you press the Index breadcrumb, it will open the page, where you entered from.
Some advantages againts session implementation (#user1764431 solution):
Each of your tab can return to it's own last page
Simple and stupid solution
Some disadvantages:
If you need to store some filter params, url could stretch very long
Just add following Code in every controller of actionIndex() rest all things will take care
$searchModel = new CentervideosSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
/*Code insertion block begin*/
$params = Yii::$app->request->queryParams;
if (count($params) <= 1)
{
$params = Yii::$app->session['customerparams'];
if(isset(Yii::$app->session['customerparams']['page']))
$_GET['page'] = Yii::$app->session['customerparams']['page'];
if(isset(Yii::$app->session['customerparams']['per-page']))
$_GET['per-page'] = Yii::$app->session['customerparams']['per-page'];
}
else
{
Yii::$app->session['customerparams'] = $params;
}
$dataProvider = $searchModel->search($params);
/*Code insertion block Ends*/
I want to change OctoberCMS backend menu organization.
Example:
I want to move from sidebar of Rainlab Plugin Static Pages - Menus to OctoberCMS CMS SideBar or it can be possible to add Rainlab Plugin Static Pages - Menus to main menu.
You can do this in your plugin.php file with registerNavigation function. For example this code define top menu and sidebar menu:
return [
'title' => [
'label' => 'title',
'url' => Backend::url('...'),
'icon' => 'icon-cube',
'permissions' => ['access.*'],
'order' => 501,
'sideMenu' => [
'title' => [
'label' => '....',
'url' => Backend::url('....'),
'icon' => 'icon-slack',
'permissions' => ['access'],
'order' => 500,
],
Also in your controller you must define this:
BackendMenu::setContext('Author.Plugin Name', 'plugin', 'model');
I know this might be really obvious but I'll still say it just to be sure. If you are looking at changing the appearance or location of Backend Menu Items provided by plugins you did not author, don't make any changes to those files yourself. You would just loose all such custom changes everytime you update that plugin.
A better idea would be to create your own plugin that uses the 3rd-party plugin as a dependency and then make required changes to this new plugin.
Example Case: You wish to alter the display of the RainLab.User plugin backend menu item.
Create a new plugin and name it as needed. For ex: Acme.UserExtension.
Now in the plugin.php file of this new plugin you can add a dependency on the RainLab.User plugin and then hide it's menu item like so:
public $require = ['RainLab.User'];
public function boot()
{
/** Add a side-menu item */
Event::listen('backend.menu.extendItems', function($manager) {
$manager->addSideMenuItem('RainLab.User', 'user', [
'payments' => [
'label' => '...'
]
]);
});
/** Add a custom main-menu item */
Event::listen('backend.menu.extendItems', function($manager) {
$manager->addMainMenuItem('Acme.UserExtension', 'user');
});
/** Remove the original main-menu item */
Event::listen('backend.menu.extendItems', function($manager) {
$manager->removeMainMenuItem('RainLab.User', 'user');
});
}
As you can see you can completely remove a menu item for a plugin you dont own if you want. You could just extend it like shown above and just use the registerNavigation() method to do what you need for this extension plugin. You might have to replicate some of the menu items you do want to retain from the original parent plugin but now you have the ability to add some of your own or remove the items you don't need.
More details on how you can do this are here -> http://octobercms.com/docs/plugin/extending#extending-backend-menu
Hopefully this isn't too convoluted and helps you out.
While extending standard October backend controllers is very easy and described in documentation (mentioned in answers above), manipulations with Static Pages by RainLab are more complicated as "side navigation" (tabs) is handled with JavaScript. It's not possible to add a new item to this plugin navigation through the methods from the October CMS docs or to add "menu" sidemenu item to another plugin. With standard extend it's possible to show only one tab (you were asking about menu) but this won't set it as default and "pages" will still be shown as default.
If you are using only Static Menu my solution is to rename top menu Pages -> Menus and hide all tabs except "menu" with permissions (they will still be visible for admin but at least won't confuse backend editor). Will be happy if someone will share a better solution.
The code to place in your custom plugin, in boot() + don't forget to set permissions while creating a backend user for the client.
// Rename rainlab.menu pages to menu
Event::listen('backend.menu.extendItems', function($manager)
{
$manager->addMainMenuItems('RainLab.Pages', [
'pages' => [
'label' => 'Menu',
'url' => Backend::url('rainlab/pages'),
'icon' => 'icon-align-justify',
'sideMenu' => [
'menus' => [
'label' => 'rainlab.pages::lang.menu.menu_label',
'icon' => 'icon-sitemap',
'url' => 'javascript:;',
'attributes' => ['data-menu-item'=>'menus'],
'permissions' => ['rainlab.pages.manage_menus']
],
]
],
]);
});
I am looking to add FedEx SmartPost as a shipping option. Any idea what I need to do to accomplish this? The only information I have found on it is here https://drupal.org/node/793124, but it seems no one has solved this issue. I am willing to modify the ubercart fedex module if needed.
So far what I have done:
Changed RateService_v10.wsdl to RateService_v14.wsdl
Added code to the uc_fedex_rate_request function:
$request['RequestedShipment']['SmartPostDetail'] = addSmartPostDetail();
function addSmartPostDetail(){
$smartPostDetail = array(
'Indicia' => 'PARCEL_SELECT',
'AncillaryEndorsement' => 'CARRIER_LEAVE_IF_NO_RESPONSE',
'SpecialServices' => 'USPS_DELIVERY_CONFIRMATION',
'HubId' => 5087,
'CustomerManifestID' => myid,
);
return $smartPostDetail;
}
In the uc_fedex_quote function, I have added a debug statement right after:
$response = uc_fedex_rate_request($packages, $origin, $destination);
drupal_set_message('<pre>'. print_r($response, TRUE) .'</pre>');
In the response I do not get SmartPost returned as an option.
This is what I had to do (note: I edited the uc_fedex.module directly):
You must get SmartPost approved for your account first
Get the updated wsdl file from https://www.fedex.com/us/developer/web-services/process.html?tab=tab1 and upload them to your server
Get a HubId from customer support (mine was 5185)
Get a CustomerManifestID from customer support
Change to RateService_v14.wsdl in the code (near $client = new SoapClient...)
Change the version to 14
$request['Version'] = array(
'ServiceId' => 'crs',
'Major' => '14',
'Intermediate' => '0',
'Minor' => '0',
);
Add the following code:
$request['RequestedShipment']['SmartPostDetail'] = addSmartPostDetail();
function addSmartPostDetail(){
$smartPostDetail = array(
'Indicia' => 'PARCEL_SELECT',
'AncillaryEndorsement' => 'CARRIER_LEAVE_IF_NO_RESPONSE',
'SpecialServices' => 'USPS_DELIVERY_CONFIRMATION',
'HubId' => yourhubid,
'CustomerManifestID' => yourmanifestid,
);
return $smartPostDetail;
}
Add the following to _uc_fedex_ground_services(): 'SMART_POST' => t('FedEx Smart Post'),
Go to admin/store/settings/quotes/methods/fedex and check 'FedEx Smart Post'
AllisonC's answer was very helpful. For anyone setting up SmartPost API calls with Drupal + Ubercart, here's how I built on her solution using FedEx Shipping 7.x-2.0+23-dev.
Download an updated RateService_vXX.wsdl file from http://www.fedex.com/us/developer/web-services/process.html?tab=tab1 (current version is v18). Open the wsdl file in a text editor and make sure it is connecting to the FedEx production server (currently ws.fedex.com:443/web-services/). Upload this file to /uc_fedex/wsdl-production/.
Edit the uc_fedex.module as follows (line numbers may vary, depending on how you edit the file):
Consider disable caching of SOAP WSDL while testing (line 19).
Define the addSmartPostDetail function as follows, outside the uc_fedex_quote function (I used line 248):
function addSmartPostDetail(){
$smartPostDetail = array(
'Indicia' => 'PARCEL_SELECT',
'HubId' => '5185', // use 5531 for testing only
);
return $smartPostDetail;
}
Inside the uc_fedex_quote function (line 271), call the addSmartPostDetail function.
$request['RequestedShipment']['SmartPostDetail'] = addSmartPostDetail();
Add the following to the _uc_fedex_ground_services() array (line 857):
'SMART_POST' => t('FedEx Smart Post'),
Define package dimensions (line 544). SmartPost has minimum container sizes of 6" L, 4" W, 1" H, and the module's hardwired settings are not adequate.
'Dimensions' => array(
'Length' => 6,
'Width' => 4,
'Height' => 1,
'Units' => 'IN',
),
I also manually patched the .module file using the patch at https://www.drupal.org/node/1782298 to avoid an unhelpful "Recoverable fatal error" notice if the request didn't work correctly.
Go to admin/store/settings/quotes/methods/fedex and check "FedEx Smart Post'.
My client needed to set conditions separately for Home Delivery and Smart Post, and didn't use any Express services, so I moved the 'SMART_POST' => t('FedEx Smart Post'), snippet to the _uc_fedex_express_services() array, enabled the FedEx Express method, and then set conditions accordingly.
Using Kohana 3.3, I created a tabbed interface and I'm trying to detect which tab is active based on a route parameter.
Testing with 2 urls which look like this: mysite.com/p/mycontroll
and: mysite.com/p/Francis-Lewis/mycontroll
My route looks like this:
Route::set('profile', 'p(/<name>)(/<controller>(/<action>))', array(
'name' => '[\w\-]+',
'controller' => '[a-z]+',
'action' => '(view|edit|save|delete|create|cancel)',
))->defaults(array(
'name' => null,
'directory' => 'profile',
'controller' => 'main',
'action' => 'index',
));
The route itself is working fine, selecting the mycontroll controller.
Here's where the problem comes in.
In the controller:
$this->request->param('controller'); // returns NULL
In the view
<?= Request::current()->param('controller') ?> // returns NULL
After banging my head around for a while, I added a function to the Kohana Request class to return the $_params array to see what was in there.
Here's all it returns:
name => 'Francis Lewis'
Any ideas how to get the current controller?
There is a function for that in in the request object:
$this->request->controller(); // Returns the current controller as a String
If you are absolutely sure that you want the initial controller then you can use the next method:
Request::initial()->controller();
otherwise use this method:
Request::current()->controller();