I am trying to generate a captcha in yii2 with a verify code in number instead of string.
is there any way?
Extend CaptchaAction with your own class and override generateVerifyCode() there like:
<?php
namespace common\captcha;
use yii\captcha\CaptchaAction as DefaultCaptchaAction;
class CaptchaAction extends DefaultCaptchaAction
{
protected function generateVerifyCode()
{
if ($this->minLength > $this->maxLength) {
$this->maxLength = $this->minLength;
}
if ($this->minLength < 3) {
$this->minLength = 3;
}
if ($this->maxLength > 8) {
$this->maxLength = 8;
}
$length = mt_rand($this->minLength, $this->maxLength);
$digits = '0123456789';
$code = '';
for ($i = 0; $i < $length; ++$i) {
$code .= $digits[mt_rand(0, 9)];
}
return $code;
}
}
In this example class is saved in common\captcha folder. Remember to change the namespace if you would like to save it somewhere else.
Now you just need to use it in controller:
public function actions()
{
return [
'captcha' => [
'class' => 'common\captcha\CaptchaAction', // change this as well in case of moving the class
],
];
}
The rest is exactly the same like with default captcha.
Related
In Silverstripe 4 I have a
DataObject 'PublicationObject',
a 'PublicationPage' and
a 'PublicationPageController'
PublicationObjects are displayed on PublicationPage through looping a PaginatedList. There is also a Pagination, showing the PageNumbers and Prev & Next - Links.
The Detail of PublicationObject is shown as 'Dataobject as Pages' using the UrlSegment.
If users are on the Detail- PublicationObject i want them to get back to the PublicationPage (the paginated list) with a Back - Link.
Two situations:
The user came from PublicationPage
and
The User came from a Search - Engine (Google) directly to the
DataObject- Detail.
I have done this like so:
$parentPage = Page::get()->Filter(array('UrlSegment' => $request->param('pageID')))->First();
$back = $_SERVER['HTTP_REFERER'];
if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
// referer not from the same domain
$back = $parentPage->Link();
}
}
Thats not satisfying.
Question:
How do i get the Pagination - Link ( e.g: ...publicationen?start=20 ) when we are on the Detail - DataObject? How can we find the Position of the current Dataobject in that paginatedList in correlation with the Items per Page? (The Page- Link This Dataobject is on)
<?php
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\View\Requirements;
use SilverStripe\Core\Convert;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\ORM\PaginatedList;
use SilverStripe\Control\Director;
use SilverStripe\ORM\DataObject;
use SilverStripe\ErrorPage\ErrorPage;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Backtrace;
class PublicationPageController extends PageController
{
private static $allowed_actions = ['detail'];
private static $url_handlers = array(
);
public static $current_Publication_id;
public function init() {
parent::init();
}
public function detail(HTTPRequest $request)
{
$publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
if (!$publication) {
return ErrorPage::response_for(404);
}
// HERE I WANT TO FIND THE POSITION OF THE DATAOBJECT IN THE PAGINATEDLIST OR RATHER THE PAGE - LINK THIS DATAOBJECT IS IN
//$paginatedList = $this->getPaginatedPublicationObjects();
//Debug::show($paginatedList->find('URLSegment', Convert::raw2sql($request->param('ID'))));
//Debug::show($paginatedList->toArray());
$parentPage = Page::get()->Filter(array('UrlSegment' => $request->param('pageID')))->First();
$back = $_SERVER['HTTP_REFERER'];
if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
// referer not from the same domain
$back = $parentPage->Link();
}
}
static::$current_Publication_id = $publication->ID;
$id = $publication->ID;
if($publication){
$arrayData = array (
'Publication' => $publication,
'Back' => $back,
'SubTitle' => $publication->Title,
'MetaTitle' => $publication->Title,
);
return $this->customise($arrayData)->renderWith(array('PublicationDetailPage', 'Page'));
}else{
return $this->httpError(404, "Not Found");
}
}
public function getPaginatedPublicationObjects()
{
$list = $this->PublicationObjects()->sort('SortOrder');
return PaginatedList::create($list, $this->getRequest()); //->setPageLength(4)->setPaginationGetVar('start');
}
}
EDIT:
is there a more simple solution ? than this ? :
public function detail(HTTPRequest $request)
{
$publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
if (!$publication) {
return ErrorPage::response_for(404);
}
//*******************************************************
// CREATE BACK - LINK
$paginatedList = $this->getPaginatedPublicationObjects();
$dO = PublicationObject::get();
$paginationVar = $paginatedList->getPaginationGetVar();
$sqlQuery = new SQLSelect();
$sqlQuery->setFrom('PublicationObject');
$sqlQuery->selectField('URLSegment');
$sqlQuery->setOrderBy('SortOrder');
$rawSQL = $sqlQuery->sql($parameters);
$result = $sqlQuery->execute();
$list = [];
foreach($result as $row) {
$list[]['URLSegment'] = $row['URLSegment'];
}
$list = array_chunk($list, $paginatedList->getPageLength(), true);
$start = '';
$back = '';
$i = 0;
$newArray = [];
foreach ($list as $k => $subArr) {
$newArray[$i] = $subArr;
unset($subArr[$k]['URLSegment']);
foreach ($newArray[$i] as $key => $val) {
if ($val['URLSegment'] === Convert::raw2sql($request->param('ID'))) {
$start = '?'.$paginationVar.'='.$i;
}
}
$i = $i + $paginatedList->getPageLength();
}
$back = Controller::join_links($this->Link(), $start);
// END CREATE BACK - LINK
//*****************************************************
static::$current_Publication_id = $publication->ID;
$id = $publication->ID;
if($publication){
$arrayData = array (
'Publication' => $publication,
'Back' => $back,
'MyLinkMode' => 'active',
'SubTitle' => $publication->Title,
'MetaTitle' => $publication->Title,
);
return $this->customise($arrayData)->renderWith(array('PublicationDetailPage', 'Page'));
}else{
return $this->httpError(404, "Not Found");
}
}
You can simply pass the page number as a get var in the URL from the PublicationPage. The detail() method can then grab the get var and if there's a value for the page number passed in, add it to the back link's URL.
In the template:
<% loop $MyPaginatedList %>
Click me
<% end_loop %>
In your controller's detail() method:
$pageNum = $request->getVar('onPage');
if ($pageNum) {
// Add the pagenum to the back link here
}
Edit
You've expressed that you want this to use the page start offset (so you can just plug it into the url using ?start=[offset]), and that you want an example that also covers people coming in from outside your site. I therefore propose the following:
Do as above, but using PageStart instead of CurrentPage - this will mean you don't have to re-compute the offset any time someone clicks the link from your paginated list.
If there is no onPage (or pageOffset as I've renamed it below, assuming you'll use PageStart) get variable, then assuming you can ensure your SortOrder values are all unique, you can check how many items are in the list before the current item - which gives you your item offset. From that you can calculate what page it's on, and what the page offset is for that page, which is your start value.
public function detail(HTTPRequest $request)
{
$publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
$paginatedList = $this->getPaginatedPublicationObjects();
// Back link logic starts here
$pageOffset = $request->getVar('pageOffset');
if ($pageOffset === null) {
$recordOffset = $paginatedList->filter('SortOrder:LessThan', $publication->SortOrder)->count() + 1;
$perPage = $paginatedList->getPageLength();
$page = floor($recordOffset / $perPage) + 1;
$pageOffset = ($page - 1) * $perPage;
}
$back = $this->Link() . '?' . $paginatedList->getPaginationGetVar() . '=' . $pageOffset;
// Back link logic ends here
//.....
}
First I code without use RequestInterface and runwell, but I when I applicate the RequestInterface from the docs here: https://codeigniter4.github.io/userguide/incoming/incomingrequest.html I got this error, What happen with my code?
<?php namespace App\Controllers;
use CodeIgniter\HTTP\RequestInterface;
class Parsys extends BaseController {
protected $request;
public function __construct(RequestInterface $request) {
$this->request = $request;
}
public function index() {
$data = [
'title' => "Parameter System",
];
return view("backend/parsys_frm", $data);
}
public function getList() {
$frm = $request->getGet('frm');
$q = $this->request->getGet('q');
$order_by = $this->request->getGet('order_by');
$page = $this->request->getGet('page');
$limit = $this->request->getGet('limit');
$limit = #$limit == 0 ? 10 : $limit;
$this->queryList($total, $current, $page, $limit, $q, [1 => 1]);
$data = $current->result_array();
header('Content-Type: application/json');
echo json_encode(compact(['total', 'page', 'limit', 'data', 'q']));
}
I use ubuntu 20.04, lampp PHP 7.4
Instead of using the __construct magic method use the built in init method.
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
}
Controller:
public function search_products_auto(){
$this->load->helper(array('form', 'url','common'));
$this->load->library(array('session','pagination'));
$this->load->model('homemodel','',TRUE);
$this->homemodel->search_products_auto();
}
public function search($subcategory=''){
$this->load->helper(array('form', 'url','common'));
$this->load->library(array('session','pagination'));
$this->load->model('homemodel','',TRUE);
$search_name=$this->input->post("title"); // first get search character
$data['records']=$this->homemodel->search($search_name,$_GET); // SearchModel is the model class name
$data['category']=$this->homemodel->getAllCategories();
$data['subcategory']=$subcategory;
$data['mens']=$this->homemodel->getAllMen();
$data['womens']=$this->homemodel->getAllWomen();
$data['scarves']=$this->homemodel->getAllScarve();
$data['collections']=$this->homemodel->getAllCollection();
$data['material']=['Cotton'=>'Cotton','Polyster'=>'Polyster'];
$data['color']=['Red'=>'Red','Black'=>'Black','Blue'=>'Blue','Green'=>'Green','Orange'=>'Orange','Black'=>'Black'];
$data['size'] =['S'=>'S','M'=>'M','L'=>'L','XL'=>'XL','XXL'=>'XXL','XXL'=>'XXL'];
$data['subcat']=$this->homemodel->getAllSubCat($search_name,$_GET);
$data['price']=$this->homemodel->getPrice($search_name,$_GET);
$this->load->view('products',$data);
}
Model:
function search($search_name,$search=array(),$cat_array=array()){
$search=array_filter($search);
$this->db->select('product.*');
$this->db->select('product_images.features');
$this->db->select('product_images.image');
$this->db->from('product');
$this->db->join('product_images',"product.id=product_images.product_id and product_images.features='yes'");
$this->db->join('product_material',"product.id=product_material.product_id",'left');
$this->db->join('product_color',"product.id=product_color.product_id",'left');
$this->db->join('product_size',"product.id=product_size.product_id",'left');
if(isset($cat_array->sub_cat_id) && $cat_array->sub_cat_id!=''){
$this->db->where('product.product_subcategory',$cat_array->sub_cat_id);
}
if(isset($search['material']) && $search['material']!=''){
$this->db->where_in('product_material.material',explode(",",$search['material']));
}
if(isset($search['color']) && $search['color']!=''){
$this->db->where_in('product_color.color',explode(",",$search['color']));
}
if(isset($search['size']) && $search['size']!=''){
$this->db->where_in('product_size.size',explode(",",$search['size']));
}
if(isset($search['price']) && $search['price']!=''){
$this->db->where_in('product.product_price',explode(",",$search['price']));
}
if(isset($search['search']) && $search['search']!=''){
$this->db->or_like(array('product.product_name'=>$search['search'],'product.sku_number'=>$search['search']));
}
$this->db->or_like(array('product.product_name'=>$search_name,'product.sku_number'=>$search_name));
$this->db->where("product.status='active'");
$this->db->group_by(['product_color.product_id','product_material.product_id','product_size.product_id']);
$query=$this->db->get();
$result=$query->result();
return $result;
}
function search_products_auto(){
$search_item = $this->input->post('query');
$this->db->select(['product.id','product.product_name','product.sku_number']);
$this->db->from('product');
if($search_item!=''){
$this->db->or_like(array('product.product_name'=>$search_item,'product.sku_number'=>$search_item));
}
$this->db->where("product.status='active'");
$query=$this->db->get();
$result=$query->result();
$dataSearch=[];
if(count($result)>0){
$i=0;
foreach($result as $results)
{
$dataSearch[$i]['id']=isset($results->id)?$results->id:"";
$dataSearch[$i]['name']=isset($results->product_name)?$results->product_name:"";
$dataSearch[$i]['name']=isset($results->sku_number)?$results->sku_number:"";
$i++;
}
}
echo json_encode($dataSearch);
}
Now, I am getting only sku number values in search bar...not the other value. How can I get all three in one search bar. I am unable to understand the concept of integrating three into one array.Rest of the things are working properly, except this search bar and also the search results are also not fine.
Please try these code it may help you, I have change only in Model:
function search($search_name, $search=array(), $cat_array=array()){
$search = array_filter($search);
$this->db->select('product.*');
$this->db->select('product_images.features');
$this->db->select('product_images.image');
$this->db->from('product');
$this->db->join('product_images',"product.id=product_images.product_id and product_images.features='yes'");
if(isset($cat_array->sub_cat_id) && $cat_array->sub_cat_id!=''){
$this->db->where('product.product_subcategory',$cat_array->sub_cat_id);
}
if(isset($search['price']) && $search['price']!=''){
$this->db->where_in('product.product_price',explode(",", $search['price']));
}
if(isset($search['search']) && $search['search']!=''){
$this->db->or_like(array('product.product_name' => $search['search'],'product.sku_number' => $search['search']));
}
if(isset($search['material']) && $search['material']!=''){
$this->db->join('product_material',"product.id=product_material.product_id",'left');
$this->db->where_in('product_material.material',explode(",",$search['material']));
}
if(isset($search['color']) && $search['color']!=''){
$this->db->join('product_color',"product.id=product_color.product_id",'left');
$this->db->where_in('product_color.color',explode(",",$search['color']));
}
if(isset($search['size']) && $search['size']!=''){
$this->db->join('product_size',"product.id=product_size.product_id",'left');
$this->db->where_in('product_size.size',explode(",",$search['size']));
}
$this->db->or_like( array('product.product_name' => $search_name, 'product.sku_number' => $search_name));
$this->db->where("product.status='active'");
$this->db->group_by(['product_color.product_id','product_material.product_id','product_size.product_id']);
$query = $this->db->get();
$result_array = $query->result_array();
/* $result=$query->result(); */
return $result_array;
}
function search_products_auto(){
$search_item = $this->input->post('query');
$this->db->select(['product.id','product.product_name','product.sku_number']);
$this->db->from('product');
if($search_item != ''){
$this->db->or_like(array('product.product_name' => $search_item, 'product.sku_number' => $search_item));
}
$this->db->where("product.status","active");
$query = $this->db->get();
/* $result=$query->result();
$dataSearch=[];
if(count($result)>0){
$i=0;
foreach($result as $results)
{
$dataSearch[$i]['id']=isset($results->id)?$results->id:"";
$dataSearch[$i]['name']=isset($results->product_name)?$results->product_name:"";
$dataSearch[$i]['sku_number']=isset($results->sku_number)?$results->sku_number:"";
$i++;
}
}
echo json_encode($dataSearch); */
echo json_encode($query->result_array());
}
I am trying to overwrite a template file located in vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig (I want to replace the "block selection" dropdown). Regarding to #1173, #1269, #5588, #3768 and #5102 this is not supported by default so I have to write a extension for this. So I tried this:
BackendBlockSelectionExtension:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Bolt\Extension\SimpleExtension;
class BackendBlockSelectionExtension extends SimpleExtension
{
public function getServiceProviders()
{
return [
$this,
new BackendBlockSelectionProvider(),
];
}
}
BackendBlockSelectionProvider:
namespace Bundle\Site;
use Bolt\Filesystem\Adapter\Local;
use Bolt\Filesystem\Filesystem;
use Silex\Application;
use Silex\ServiceProviderInterface;
class BackendBlockSelectionProvider implements ServiceProviderInterface
{
public function register(Application $app)
{
$side = $app['config']->getWhichEnd();
if ($side == 'backend') {
$path = __DIR__ . '/App/templates/Backend';
$filesystem = $app['filesystem'];
$filesystem->mountFilesystem('bolt', new Filesystem(new Local($path)));
$app['twig.loader.bolt_filesystem'] = $app->share(
$app->extend(
'twig.loader.bolt_filesystem',
function ($filesystem, $app) {
$path = __DIR__ . 'src/App/templates/Backend/';
$filesystem->prependPath($path, 'bolt');
return $filesystem;
}
)
);
}
}
public function boot(Application $app)
{
}
}
This seems to do the job, but I got an error I don't understand at all: The "bolt://app/theme_defaults" directory does not exist.
So my final question is: Does anyone have some example code how to overwrite/modify vendor/bolt/bolt/app/view/twig/editcontent/fields/_block.twig without touching the vendor folder?
This should be much simplier than this.
In your extension class overwrite protected function registerTwigPaths() function like this:
protected function registerTwigPaths()
{
if ($this->getEnd() == 'backend') {
return [
'view' => ['position' => 'prepend', 'namespace' => 'bolt']
];
}
return [];
}
private function getEnd()
{
$backendPrefix = $this->container['config']->get('general/branding/path');
$end = $this->container['config']->getWhichEnd();
switch ($end) {
case 'backend':
return 'backend';
case 'async':
// we have async request
// if the request begin with "/admin" (general/branding/path)
// it has been made on backend else somewhere else
$url = '/' . ltrim($_SERVER['REQUEST_URI'], $this->container['paths']['root']);
$adminUrl = '/' . trim($backendPrefix, '/');
if (strpos($url, $adminUrl) === 0) {
return 'backend';
}
default:
return $end;
}
}
Now you can crete a view directory in your extensions directory in which you can define templates in structure like in Bolt's default. I would start with copy and overwrite.
Pagination not work properly?
I saved this code in "Forum-Com.php" file and when i open this file, pagination works properly and correctly but when I include this file in another page, its open first page correctly but when I click second or another page link it open same comments which are on first page. Please help me. ( I am using Scriptsmill comments script v1.06 and function make_pages_string from admin.php )
$COM_CONF['full_path'] = dirname(__FILE__);
function make_pages_string ($all_count, $records_per_page, $cur_page, $base_url) {
if ($all_count > $records_per_page) {
if ($cur_page > 0) { $cur_page=$cur_page-1; }
$first_record = ($cur_page) * $records_per_page;
$limit_string = "LIMIT $first_record, $records_per_page";
$pages=$all_count/$records_per_page;
if ($pages > (int) $pages) { $pages=(int)$pages+1; }
}
if ($pages>1) {
$pages_string.="Page: ";
if ($cur_page>10 && $pages>20) { $first_page=$cur_page-9; }
else { $first_page=1; }
if ($pages>20 && ($cur_page+10)<$pages) { $last_page=$first_page+19; }
else { $last_page=$pages; }
if ($cur_page+1>1) {
$prev=$cur_page;
$pages_string.="<a href='$base_url&page=$prev'><</a> ";
}
for ($i=$first_page; $i<=$last_page; $i++){
if ($i != $cur_page+1) {
$pages_string.="<a href='$base_url&page=$i'>$i</a> ";
}
else {
$pages_string.="<b>$i</b> ";
}
}
if ($cur_page+1<$pages) {
$next=$cur_page+2;
$pages_string.="<a href='$base_url&page=$next'>></a> ";
}
}
return array ($pages_string, $limit_string);
}
function smcom_view()
{
global $comments_db_link, $COM_CONF, $COM_LANG;
$result = mysql_query("select COUNT(id) from {$COM_CONF['dbmaintable']}", $comments_db_link);
list ($all_count) = mysql_fetch_row($result);
list ($pages_string, $limit_string) = make_pages_string ($all_count, 10, $_REQUEST['page'], "{$COM_CONF['base_url']}?action=view");
$result = mysql_query("select time, text, author, email, dont_show_email from {$COM_CONF['dbmaintable']} order by time {$COM_CONF['sort_order']} $limit_string", $comments_db_link);
$comments_count=0;
$id=$time=$text=$author=$email=$dont_show_email=$ip=array();
while (list($id[$comments_count], $time[$comments_count], $text[$comments_count], $author[$comments_count], $email[$comments_count], $dont_show_email[$comments_count], $ip[$comments_count])=mysql_fetch_array($result)) {
$comments_count++;
}
require("{$COM_CONF['full_path']}/templates/Forum-default.php");
}
The code given above has no problem at all. The problem is with the server configuration which turned off $_REQUEST global variable from direct access.