I have a class that registers a new endpoint, rewrites rules and then flushes it. It works perfectly except that it also gives a 404 error, making the page title "page not found" and adding some css which I dont want. I need to make it so that it actually knows my page exists.
This is the class I wrote:
<?php
use Jigoshop\Helper\Render as RenderCore;
use Jigoshop\Frontend\Page\PageInterface;
use Jigoshop\Integration\Helper\Render;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class twizo_Jigoshop_TFASettings implements PageInterface
{
function __construct()
{
Render::addLocation('twizo-verification', __DIR__);
add_action('init', function () {
add_rewrite_endpoint("twizo-verification", EP_ROOT | EP_PAGES |
EP_PERMALINK);
add_filter('generate_rewrite_rules', function ($rewrite) {
$mySettings = [
'^account/twizo-verification/?$' => 'index.php?
pagename=twizo-verification'
];
$rewrite->rules = $mySettings + $rewrite->rules;
return $rewrite->rules;
});
flush_rewrite_rules();
});
add_filter('jigoshop.frontend.page_resolver.page', function ($args) {
global $wp_query;
if ($wp_query->query['pagename'] == 'twizo-verification') {
return $this;
}
return $args;
});
}
public function action()
{
$this->renderTFASettings();
}
public function render()
{
}
public function renderTFASettings()
{
add_action('jigoshop\template\shop\content\before', function () {
echo '<h1>My account » 2FA Settings</h1>';
});
add_action('jigoshop\template\shop\content\after', function() {
echo '<br><a href="./" class="btn btn-default">Go back to My
account</a>';
});
switch(get_template()) {
case "twentyfifteen":
RenderCore::output('layout/twentyfifteen', [
'content' => Render::get('twizo-verification', 'tfa-
settings-body', array())
]);
break;
case "twentysixteen":
RenderCore::output('layout/twentysixteen', [
'content' => Render::get('twizo-verification', 'tfa-
settings-body', array())
]);
break;
case "twentyseventeen":
RenderCore::output('layout/twentyseventeen', [
'content' => Render::get('twizo-verification', 'tfa-
settings-body', array())
]);
break;
default:
RenderCore::output('layout/default', [
'content' => Render::get('twizo-verification', 'tfa-
settings-body', array())
]);
break;
}
exit;
}
}
Related
I currently have a working controller that extends WP_REST_Controller in a file under the current theme. These are being called using jQuery ajax. (all code below)
The issue I am facing is that I receive this error ONLY when accessing with a mobile device.
{"code": "rest_no_route", "message": "No route was found matching the URL and request method" "data": {"status": 404}}
settings -> permalinks -> save changes
tried using controller namespace "api/v1" and "wp/v2"
javascript
function getAllClients() {
jQuery.ajax({
url: "http://myurl.com/index.php/wp-json/wp/v2/get_all_clients",
type: "GET",
data: { /*data object*/},
success: function (clientList) {
// success stuff here
},
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.statusText);
}
})
}
api/base.php
<?php
class ApiBaseController extends WP_REST_Controller
{
//The namespace and version for the REST SERVER
var $my_namespace = 'wp/v';
var $my_version = '2';
public function register_routes()
{
$namespace = $this->my_namespace . $this->my_version;
register_rest_route(
$namespace,
'/get_all_clients',
array(
array(
'methods' => 'GET',
'callback' => array(new ApiDefaultController('getAllClients'), 'init'),
)
)
);
$ApiBaseController = new ApiBaseController();
$ApiBaseController->hook_rest_server();
api/func.php
<?php
class ApiDefaultController extends ApiBaseController
{
public $method;
public $response;
public function __construct($method)
{
$this->method = $method;
$this->response = array(
// 'Status' => false,
// 'StatusCode' => 0,
// 'StatusMessage' => 'Default'
// );
}
private $status_codes = array(
'success' => true,
'failure' => 0,
'missing_param' => 150,
);
public function init(WP_REST_Request $request)
{
try {
if (!method_exists($this, $this->method)) {
throw new Exception('No method exists', 500);
}
$data = $this->{$this->method}($request);
$this->response['Status'] = $this->status_codes['success'];
$this->response['StatusMessage'] = 'success';
$this->response['Data'] = $data;
} catch (Exception $e) {
$this->response['Status'] = false;
$this->response['StatusCode'] = $e->getCode();
$this->response['StatusMessage'] = $e->getMessage();
}
return $this->response['Data'];
}
public function getAllClients()
{
// db calls here
return json_encode($stringArr,true);
}
}
These are registered in the Functions.php file
require get_parent_theme_file_path('api/base.php');
require get_parent_theme_file_path('api/func.php');
Turns out the issue was a plugin my client installed called "oBox mobile framework" that was doing some weird routing behind the scenes. Disabling it resolved the issue, though there is probably a way to hack around this and get both to play together.
I write little framework. Can't go to the url /page/test. Says page not found. Maybe something wrong with the regular expressions in the urls.php? It looks like the browser process the URL itself, however script should it does.
<?php
class griEngine {
public
$settings, //settings
$uri, //current URI
$app; //curent app
public function __construct($settings) {
$this->settings= $settings;
$this->uri = urldecode(preg_replace('/\?.*/iu','',$_SERVER['REQUEST_URI']));
$this->app = false;
$this->process_path();
$this->process_controllers();
}
public function process_path() {
foreach( $this->settings['apps'] as $iterable_app )
{
$iterable_urls = require(BASE_DIR. '/apps/'. $iterable_app. '/urls.php');
foreach( $iterable_urls as $pattern => $method)
{
$matches = array();
if (preg_match($pattern, $this->uri, $matches))
{
$this->app = array($iterable_app, array('pattern' => $pattern, 'method' => $method, 'args' => $matches));
break(2);
}
if( $this->app ==='false')
{
exit('App not found.');
}
}
public function process_controllers() {
if ($this->app || is_array($this->app))
{
require(BASE_DIR.'/apps/'.$this->app['0'].'/controller.php');
$controller_name = $this->app['0'].'_Controller';
$this->app_controller = new $controller_name();
$this->app_controller->{$this->app['1']['method']}($this->app['1']['args']);
}
}
}
file urls.php
<?php
return array(
'#^/*$#i' => 'MainPage',
'#^/Page/([A-z0-9_-])/*#i' => 'ViewPage'
);
file controller.php
<?php
class Simple_Pages_Controller extends gri_Controller {
public function MainPage($args){
echo 'Hello world';
}
public function ViewPage(){
echo 'test';
}
}
?>
You were missing + here ^/Page/([A-z0-9_-])/*#i. As test in /page/test contains more than 1 character, so you should use +
Change this to:
return array(
'#^/*$#i' => 'MainPage',
'#^/Page/([A-z0-9_-])/*#i' => 'ViewPage'
);
This:
<?php
return array(
'#^/*$#i' => 'MainPage',
'#^/Page/([A-z0-9_-]+)/*#i' => 'ViewPage'
);
I'm still trying to add a recaptcha to my website, I want try the recaptcha from Google but I can't use it properly. Checked or not, my email is still sent.
I tried to understand the code of How to validate Google reCaptcha v2 using phalcon/volt forms?.
But i don't understand where are my problems and more over how can you create an element like
$recaptcha = new Check('recaptcha');
My controller implementation :
<?php
/**
* ContactController
*
* Allows to contact the staff using a contact form
*/
class ContactController extends ControllerBase
{
public function initialize()
{
$this->tag->setTitle('Contact');
parent::initialize();
}
public function indexAction()
{
$this->view->form = new ContactForm;
}
/**
* Saves the contact information in the database
*/
public function sendAction()
{
if ($this->request->isPost() != true) {
return $this->forward('contact/index');
}
$form = new ContactForm;
$contact = new Contact();
// Validate the form
$data = $this->request->getPost();
if (!$form->isValid($data, $contact)) {
foreach ($form->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
if ($contact->save() == false) {
foreach ($contact->getMessages() as $message) {
$this->flash->error($message);
}
return $this->forward('contact/index');
}
$this->flash->success('Merci, nous vous contacterons très rapidement');
return $this->forward('index/index');
}
}
In my view i added :
<div class="g-recaptcha" data-sitekey="mypublickey0123456789"></div>
{{ form.messages('recaptcha') }}
But my problem is after : i create a new validator for the recaptcha like in How to validate Google reCaptcha v2 using phalcon/volt forms? :
use \Phalcon\Validation\Validator;
use \Phalcon\Validation\ValidatorInterface;
use \Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
if (!$this->isValid($validation)) {
$message = $this->getOption('message');
if ($message) {
$validation->appendMessage(new Message($message, $attribute, 'Recaptcha'));
}
return false;
}
return true;
}
public function isValid($validation)
{
try {
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
$url = $config->'https://www.google.com/recaptcha/api/siteverify'
$data = ['secret' => $config->mysecretkey123456789
'response' => $value,
'remoteip' => $ip,
];
// Prepare POST request
$options = [
'http' => [
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
],
];
// Make POST request and evaluate the response
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result)->success;
}
catch (Exception $e) {
return null;
}
}
}
So i don't know if tjis code is correct anyway, i have a problem too after that : how to create an object "recaptcha" in my form add
$recaptcha = new ?????('recaptcha');
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'Please confirm that you are human'
]));
$this->add($recaptcha);
PS: I apologize because i'm a noob here and my mother tongue is not english, so if you don't understand me or want give me some advices to create a proper question, don't hesitate ^^
I've made a custom form element for recaptcha. Used it for many projects so far.
The form element class:
class Recaptcha extends \Phalcon\Forms\Element
{
public function render($attributes = null)
{
$html = '<script src="https://www.google.com/recaptcha/api.js?hl=en"></script>';
$html.= '<div class="g-recaptcha" data-sitekey="YOUR_PUBLIC_KEY"></div>';
return $html;
}
}
The recaptcha validator class:
use Phalcon\Validation\Validator;
use Phalcon\Validation\ValidatorInterface;
use Phalcon\Validation\Message;
class RecaptchaValidator extends Validator implements ValidatorInterface
{
public function validate(\Phalcon\Validation $validation, $attribute)
{
$value = $validation->getValue('g-recaptcha-response');
$ip = $validation->request->getClientAddress();
if (!$this->verify($value, $ip)) {
$validation->appendMessage(new Message($this->getOption('message'), $attribute, 'Recaptcha'));
return false;
}
return true;
}
protected function verify($value, $ip)
{
$params = [
'secret' => 'YOUR_PRIVATE_KEY',
'response' => $value,
'remoteip' => $ip
];
$response = json_decode(file_get_contents('https://www.google.com/recaptcha/api/siteverify?' . http_build_query($params)));
return (bool)$response->success;
}
}
Using in your form class:
$recaptcha = new Recaptcha($name);
$recaptcha->addValidator(new RecaptchaValidator([
'message' => 'YOUR_RECAPTCHA_ERROR_MESSAGE'
]));
Note 1: You were almost there, you just missed to create custom form element (the first and last code piece from my example);
Note 2: Also there is a library in Github: https://github.com/fizzka/phalcon-recaptcha I have not used it, but few peeps at phalcon forum recommended it.
When i call this function first time then file downloaded but after refresh the page it show me some not understanding character on my browser screen
// Controller Code
public function actionDownload($id)
{
$model = $this->findModel($id);
$file ='../frontend/uploads/users/'.$model->image;
if(file_exists($file))
{
return Yii::$app->response->sendFile($file);
exit;
}
//Button Code
[
'attribute'=>'resume',
'label'=>'Resume',
'format'=>'raw',
'value'=>function($data)
{
if($data->resume != null)
{
// $url = Yii::$app->params['application_base'].'admin/user/download/'.$data->id;
return Html::a('Download', ['download','id'=> $data->id]);
}
else
{
return 'NA';
}
},
],
Try to omit a pjax amd use
return Html::a('Download', ['download','id'=> $data->id, 'data-pjax' => 0]);
instead of
return Html::a('Download', ['download','id'=> $data->id]);
After any ajax request all subsequent non ajax request is returning with ajax layout instead of default layout.
Obs:
Ocurrs only on production enviroment.
Configure::write('Cache.disable', true); // Don't have any effect!
Cake Version 2.4.4
After 20 ~ 30 seconds the layout (default) is rendered.
config/core.php is identical.
I don't no why , and i loose 8 hours on that, any tip?
The controller (But any ajax on any controller cause the problem:
<?php
App::uses('AppController', 'Controller');
class NewslettersController extends AppController
{
public $paginate = array(
'limit' => 20,
'paramType' => 'querystring',
'order' => array(
'Newsletter.created' => 'DESC'
)
);
public function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow(array('add','push'));
}
public function admin_index()
{
$this->set('dataGrid', $this->paginate('Newsletter'));
}
public function admin_view($id = null)
{
$this->Newsletter->id = $id;
$result = $this->Newsletter->read();
if (!$result) {
$this->setFlashMessage('Cadastro não encontrado', 'error', array('action' => 'index'));
return false;
}
$this->set('dataGrid', $result);
}
public function admin_delete($id = null)
{
$this->Newsletter->id = $id;
if (!$this->Newsletter->exists()) {
$this->Session->setFlash('O item solicitado não foi encontrado!', 'alert_error');
$this->setFlashMessage('O item solicitado não foi encontrado!', 'error', array('action' => 'index'));
}
try {
if ($this->Newsletter->delete($id, false)) {
$this->setFlashMessage('Item excluído com sucesso!', 'success', array('action' => 'index'));
}
} catch (Exception $e) {
$this->setFlashMessage('Não foi possivel excluir este item pois existem itens atrelados a ele', 'error', array('action' => 'index'));
}
}
public function admin_search()
{
$this->autoRender = false;
$conditions = null;
if (isset($this->request->query['search']) && !empty($this->request->query['search'])) {
$conditions[] = array(
'OR' => array(
'Newsletter.name LIKE' => '%' . $this->request->query['search'] . '%',
'Newsletter.email LIKE' => '%' . $this->request->query['search'] . '%',
)
);
$this->paginate['conditions'] = $conditions;
$this->set('dataGrid', $this->paginate());
$this->render('admin_index');
}
}
//######################
//# FRONTEND #
//######################
public function push()
{
if($this->Newsletter->save($this->request->data))
{
$response = array("result"=>true,"id"=>$this->Newsletter->id);
}
else
{
$response = array("result"=>false,"errors"=>$this->Newsletter->validationErrors);
}
return new CakeResponse(array("body" => json_encode($response),"type" => "json"));
}
}
?>
You have to differentiate the layout for ajax in the method, please the following changes I made in the above code:
...
class NewslettersController extends AppController
{
public layout = 'default';
...
public function push() // if this is ajax function
{
$this->layout = 'ajax'; //put this for ajax functions only
....
}
...
}
Hope it helps!