So I have a function which checks a load of jobs and tries to close them. Each job is put into another function which tries to close this job and it returns an array like return ['error' => 'There are still teams working on job #' . sprintf('%07d', $this->number)]; or return ['message' => 'Successfully marked job #' . sprintf('%07d', $this->number) . ' as completed"];
So my question is how do i handle this in my layout so that all success and errors are displayed. This is the function which calls the individual function to close a job:
public function close( Project $project ): RedirectResponse
{
try {
$jobs = $project->jobs()->get();
$hasErrors = false;
foreach ( $jobs as $job ) {
$result = $job->setComplete();
foreach ( $result as $type => $message ) {
if ( $type === 'error' ) $hasErrors = true;
Session::flash( $type, $message );
}
}
if ( $hasErrors ) {
Session::flash('error', 'Project still has open Jobs, these will need to be set as complete');
} else {
$project->is_enabled = 0;
$project->save();
Session::flash('message', 'Project has been closed!');
}
} catch ( Exception $e ) {
Session::flash('error', 'Could not close this project! (' . $e->getMessage() . ')');
}
return redirect::back();
}
I will omit the $job->setComplete(); function for simplicity, it returns an array with a single row which is either an error or a success message as outlined above.
I have in my layout code which handles validation errors so it would be good if I could use this if possible? If not I'm open to suggestions!
I found a solution. I create an array of the errors and return them as a MessageBag using withErrors( $errors ) This works using existing layout to handle errors in a property bag.
public function close( Project $project ): RedirectResponse
{
$errors =[];
try {
$jobs = $project->jobs()->get();
$hasErrors = false;
foreach ( $jobs as $job ) {
$result = $job->getComplete();
foreach ( $result as $type => $message ) {
if ( $type === 'error' ) {
$hasErrors = true;
$errors[] = $message;
} else {
Session::flash( $type, $message );
}
}
}
if ( $hasErrors ) {
Session::flash('error', 'Project still has open Jobs, these will need to be set as finished first');
} else {
$project->is_enabled = 0;
$project->save();
Session::flash('message', 'Project has been closed!');
}
} catch ( Exception $e ) {
Session::flash('error', 'Could not close this project! (' . $e->getMessage() . ')');
}
return redirect::back()->withErrors( $errors );
}
Related
How do I deal with failures in Laravel's Concurrent Requests? For example I have 10 requests in a pool and half of them return GuzzleHttp\Exception\ConnectException. I want to catch them and retry with a different proxy server.
<?php
$responses = Illuminate\Support\Facades\Http::pool(
function (Illuminate\Http\Client\Pool $pool) use ($params) {
$url = "https://example.com/api/endpoint?foo=%s";
$return = [];
$proxy = $this->proxyManager->get();
foreach($params as $param) {
// Number of retries
for($i = 0; $i < 10; $i++) {
try {
// This returns GuzzleHttp\Promise\Promise
$return[] = $pool->as($param)
->withOptions(['proxy' => $proxy])
->get(\sprintf($url, $param))
->otherwise(function ($e) {
// This never happens
dd( $e );
});
break;
} catch(\Exception $e) {
$proxy = $this->proxyManager->get();
continue;
}
}
}
return $return;
}
);
// Some fail, some ok
dd( $responses );
Had to use Guzzle with custom Middleware to archive what I wanted:
app/Http/Client/Middleware.php
<?php
namespace App\Http\Client;
final class Middleware
{
public static function retry( callable $decider, callable $delay = null ): callable
{
return static function( callable $handler ) use ( $decider, $delay ): RetryMiddleware
{
return new RetryMiddleware( $decider, $handler, $delay );
};
}
}
app/Http/Client/RetryMiddleware.php
<?php
namespace App\Http\Client;
use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
class RetryMiddleware
{
private $nextHandler;
private $decider;
private $delay;
public function __construct(callable $decider, callable $nextHandler, callable $delay = null)
{
$this->decider = $decider;
$this->nextHandler = $nextHandler;
$this->delay = $delay ?: __CLASS__ . '::defaultDelay';
}
public static function defaultDelay(int $retries): int
{
return 0;
}
public function __invoke(RequestInterface $request, array $options): PromiseInterface
{
if (!isset($options['retries'])) {
$options['retries'] = 0;
}
$fn = $this->nextHandler;
return $fn($request, $options)
->then(
$this->onFulfilled($request, $options),
$this->onRejected($request, $options)
);
}
private function onFulfilled(RequestInterface $request, array $options): callable
{
return function ($value) use ($request, $options) {
if (!($this->decider)(
$options['retries'],
$request,
$value,
null
)) {
return $value;
}
return $this->doRetry($request, $options, $value);
};
}
private function onRejected(RequestInterface $req, array $options): callable
{
return function ($reason) use ($req, $options) {
if (!($this->decider)(
$options['retries'],
$req,
null,
$reason
)) {
return P\Create::rejectionFor($reason);
}
return $this->doRetry($req, $options);
};
}
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null): PromiseInterface
{
$options['delay'] = ($this->delay)(++$options['retries'], $response);
// Callback?
if( $options['on_retry'] )
{
\call_user_func_array( $options['on_retry'], [
&$request,
&$options,
$response
] );
}
return $this($request, $options);
}
}
Then make asynchronous requests like this:
<?php
$url = "https://example.com/api/endpoint?foo=%s";
$data = [];
$handlerStack = \GuzzleHttp\HandlerStack::create( new \GuzzleHttp\Handler\CurlMultiHandler() );
$handlerStack->push( \App\Http\Client\Middleware::retry( function( $retries, $request, $response = null, $exception = null )
{
// Limit the number of retries to 10
if( $retries >= 10 )
{
return false;
}
// Retry connection exceptions
if( $exception )
{
return true;
}
return false;
} ) );
$client = new \GuzzleHttp\Client( [
'handler' => $handlerStack,
'on_retry' => function( &$request, &$options )
{
$options['proxy'] = $this->proxyManager->get();
}
] );
$requests = function() use ( $client, $url, $params )
{
foreach( $params as $param )
{
$get = \sprintf( $url, $param );
yield function() use ( $client, $get )
{
return $client->getAsync( $get, [
'proxy' => $this->proxyManager->get()
] );
};
}
};
$pool = new \GuzzleHttp\Pool( $client, $requests(), [
'concurrency' => 5, // maximum number of requests to send concurrently
'fulfilled' => function( \GuzzleHttp\Psr7\Response $response, $index ) use ( &$data )
{
$data[] = json_decode( $response->getBody(), true );
}, // this is delivered each successful response
'rejected' => function( \Exception $e, $index )
{
}, // this is delivered each failed request
] );
$pool->promise()->wait();
If you want to make synchronous requests with retry then Laravel's HttpClient works:
<?php
$url = "https://example.com/api/endpoint";
$response = \Illuminate\Support\Facades\Http::withOptions( [
'proxy' => $this->proxyManager->get(),
'on_retry' => function( &$request, &$options )
{
$options['proxy'] = $this->proxyManager->get();
}
] )
->withMiddleware( \App\Http\Client\Middleware::retry( function( $retries, $request, $response = null, $exception = null )
{
// Limit the number of retries to 10
if( $retries >= 10 )
{
return false;
}
// Retry connection exceptions
if( $exception )
{
return true;
}
return false;
} ) )
->get( $url );
I do not understand how to display a notice after a term creation in WordPress.
I have a custom field in a custom taxonomy. On the save event, I check if the value is incorrect and in this case, I want to display a notice.
I have a similar situation in the post editor but here I have solved with add_settings_error and admin_notices.
This method does not work in the term creation screen because in this scenario, there is an AJAX request and the page does not reload.
Here is the code about term screen:
add_action('create_account', 'save_start_amount_data__fr');
add_action('admin_notices', 'display_start_amount_data_validation_error__fr');
function save_start_amount_data__fr($term_id) {
if (
!isset($_POST['start_amount_nonce']) ||
!wp_verify_nonce($_POST['start_amount_nonce'], 'start_amount_nonce')
) {return $term_id;}
if (
(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
) {return $term_id;}
if (
!isset($_POST['taxonomy']) ||
$_POST['taxonomy'] != 'account' ||
!current_user_can('edit_posts')
) {return $term_id;}
if (
!isset($_POST['start_amount'])
) {return $term_id;}
if (
!preg_match('/^[-]?[0-9]+([,]?[0-9]{1,2})?$/', $_POST['start_amount'])
) {validate_start_amount_data__fr();}
$start_amount = $_POST['start_amount'];
$start_amount = sanitize_text_field($start_amount);
update_term_meta($term_id, 'start_amount', $start_amount);
return $term_id;
}
function validate_start_amount_data__fr() {
add_settings_error(
'incorrect_start_amount_value',
'incorrect_start_amount_value',
__('Please review the start amount value because it is in an incorrect format.', 'fr'),
'error'
);
set_transient('settings_errors', get_settings_errors(), 30);
return null;
}
function display_start_amount_data_validation_error__fr() {
$errors = get_transient('settings_errors');
if (!$errors) {return null;}
$message = '<div class="notice notice-error"><ul>';
foreach($errors as $error) {
$message .= '<li>' . $error['message'] . '</li>';
}
$message .= '</ul></div>';
echo $message;
delete_transient('settings_errors');
remove_action('admin_notices', 'display_start_amount_data_validation_error__fr');
return null;
}
I hope that someone can help me to achieve my goal.
See below the method that I'm using on a Custom Posts to display notifications.
Take a look to the filter "redirect_post_location".
//Actions
$this->loader->add_action( 'admin_notices', $plugin_admin, 'general_admin_notice' );
$this->loader->add_action( 'save_post', $plugin_admin, 'admin_save_post' );
/**
* Admin Save the Meta box values
*
* #since 1.0.0
*/
function admin_save_post( $id ) {
/* --- security verification --- */
if(!wp_verify_nonce($_POST['attachment_nonce'], plugin_basename(__FILE__))) {
return $id;
} // end if
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return $id;
} // end if
if('page' == $_POST['post_type']) {
if(!current_user_can('edit_page', $id)) {
return $id;
} // end if
} else {
if(!current_user_can('edit_page', $id)) {
return $id;
} // end if
} // end if
/* - end security verification - */
// Make sure the file array isn't empty
if(!empty($_FILES['secure_doc_attachment']['name'])) {
$upload = $this->admin_upload_file( $_FILES , $id );
if (!$upload){
add_filter('redirect_post_location', function($loc) {
return add_query_arg( 'error', 1, $loc );
});
return $post_id;
}
}
}
/**
* Admin Notice
*
* #since 1.0.0
*/
function general_admin_notice(){
global $pagenow;
if ( 'post.php' === $pagenow && isset($_GET['post']) && 'custom-post' === get_post_type( $_GET['post'] ) ){
if ( isset($_GET['error'])) {
echo '<div class="notice notice-error is-dismissible">
<p>Error uploading the attachment.</p>
</div>';
}
}
}
See other useful link here:
https://wordpress.stackexchange.com/questions/124132/admin-post-update-redirection-to-posts-screen
Regards.
Ed.
I am working on multiple file upload code is not showing any error
public function imagenewAction()
{
$form = new ImageNewForm();
$form->get('submit')->setValue('Submit');
$request = $this->getRequest();
// die('checko');
if($request->isPost())
{
// die('checko');
$nonFile = $request->getPost()->toArray();
$File = $this->params()->fromFiles('file');
$data = array_merge_recursive($request->getPost()->toArray(), $request->getFiles()->toArray());
$form->setData($data);
if ($form->isValid())
{
//New Code
$dataNew=array('','image','image1');
for($i=1;$i<=2;$i++)
{
$addressProof = $data[$dataNew[$i]]['name'];
$addressProofextension = pathinfo($addressProof, PATHINFO_EXTENSION);
// $addressProofimg = $addressProof . $i . "." . $addressProofextension;
$addressProofimg = $addressProof;
//$verificationdocuments->setdocphotocopy($addressProofimg);
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination('public/img/upload');
$adapter->addFilter(new \Zend\Filter\File\Rename(array(
'target' => 'public/img/upload',
'overwrite' => true
)), null, $addressProofimg);
if(!$adapter->receive($addressProofimg))
{
print_r ( $adapter->getMessages (), 1 );
}
else
{
echo "Image Uploaded";
}
}
}
}
return array('form' => $form);
}
It is giving blank error messages and not uploading images please help me to get away with this I am stuck from last 2 days
I want to pass a message variable in some conditions to controller from model in codeigniter. But when i am doing this it is printing only "No" everytime.
Model is
public function add_city() {
/* Storing form data into an array */
$data = array(
'city_name' => $this->input->post('city'),
'city_overview' => $this->input->post('overview')
);
/* Checking if already exist in database */
$query = $this->db->query("SELECT * FROM city_tbl WHERE city_name='" . $data['city_name'] . "' ORDER BY id ASC");
$count_row = $query->num_rows();
if ($count_row > 0) {
$msg = "No";
} else {
$this->db->insert('city_tbl', $data);
$msg = "Yes";
}
return $msg;
}
And Controller is
public function addingCity() {
$this->add_model->add_city();
var_dump($msg);
//redirect("/city");
}
Try This also
public function add_city() {
$data = array(
'city_name' => $this->input->post('city'),
'city_overview' => $this->input->post('overview')
);
/* Checking if already exist in database */
$query = $this->db->query("SELECT * FROM city_tbl WHERE city_name='" . $data['city_name'] . "' ORDER BY id ASC");
$count_row = $query->num_rows();
if ($count_row > 0) {
$msg = "No";
} else {
$this->db->insert('city_tbl', $data);
$msg = "Yes";
}
return $msg;
}
On controller redirect message with get method -
public function addingCity() {
$msg = $this->add_model->add_city();
redirect("/city?msg=".$msg);
}
And finally print this message on view page
echo $this->input->get('msg');
You need to assign value to $msg in your controller
public function addingCity() {
$msg=$this->add_model->add_city();// assign
var_dump($msg);
//redirect("/city");
}
Try this
public function add_city() {
$city_name = $this->input->post('city');
$city_overview = $this->input->post('overview');
$query = $this->db->query("SELECT * FROM city_tbl WHERE city_name='$city_name' ORDER BY id ASC");
$result = $query->result_array()
$count = count($result);
if(empty($count))
{
$msg = "No";
return $msg;
}
else{
$data = array(
'city_name'=>$this->input->post('city'),
'city_overview'=>$this->input->post('overview') );
$this->db->insert('city_tbl', $data);
$msg = "Yes";
return $msg;
}
}
In Controller
public function addingCity() {
$msg = $this->add_model->add_city();
echo $msg;
}
To pass data to view
public function addingCity() {
$data['msg'] = $this->add_model->add_city();
$this->load->view("filename", $data); # ex $this->load->view("index", $data);
}
Error is in your controller function
Try with this code
public function addingCity() {
$msg = $this->add_model->add_city();
echo $msg;die;
//redirect("/city");
}
While i run a component i am getting 500 - An error has occurred error reading db in joomla.
My configuration file is perfect.
I don't know what else to change..
Any guidance will be helpful
Thanks in advance...
//No direct acesss
defined('_JEXEC') or die();
jimport('joomla.application.component.model');
class DealsModelDeals extends JModel {
function getDeals(){
$db = $this->getDBO();
$db->setQuery('SELECT * from #__todaysdeal');
$deals = $db->loadObjectList();
if ($deals === null)
JError::raiseError(500, 'Error reading db');
return $deals;
}
function getDeal($id){
$query = ' SELECT * FROM #__todaysdeal '. ' WHERE id = '.$id;
$db = $this->getDBO();
$db->setQuery($query);
$deal = $db->loadObject();
if ($deal === null)
JError::raiseError(500, 'Deal with ID: '.$id.' not found.');
else
return $deal;
}
/**
* Method that returns an empty greeting with id 0
*
* #access public
*/
function getNewDeal(){
$dealTableRow =& $this->getTable('deals');
$dealTableRow->id=0;
$dealTableRow->clientName='';
return $dealTableRow;
}
/**
* Method to store a greeting in the DB
*
* #access public
*/
function saveDeal($deal)
{
//Parameter not necessary because our model is named DealsModelDeals (used to ilustrate that you can specify an alternative name to the JTable extending class)
$dealTableRow =& $this->getTable('deals');
//print_r($dealTableRow);
//print_r($_FILES); exit;
// Bind the form fields to the todaysdeal table
if (!$dealTableRow->bind($deal)) {
JError::raiseError(500, 'Error binding data');
}
// Make sure the deal record is valid
if (!$dealTableRow->check()) {
JError::raiseError(500, 'Invalid data');
}
// Insert/update this record in the db
if (!$dealTableRow->store()) {
$errorMessage = $dealTableRow->getError();
JError::raiseError(500, 'Error binding data: '.$errorMessage);
}
$id = $dealTableRow->id;
if(!empty($_FILES['dealImage']))
{
$file = $_FILES['dealImage'];
$id = $dealTableRow->id;
if ((($_FILES["dealImage"]["type"] == "image/gif") || ($_FILES["dealImage"]["type"] == "image/jpeg") || ($_FILES["dealImage"]["type"] == "image/pjpeg")) && ($_FILES["dealImage"]["size"] < 150000))
{
if ($_FILES["dealImage"]["error"] > 0)
{
echo "Return Code: " . $_FILES["dealImage"]["error"] . "<br />";
}
else
{
if (file_exists("components/com_deals/dealImages/" . $_FILES["dealImage"]["name"])) {
$_FILES["dealImage"]["name"] . " already exists. ";
} else {
move_uploaded_file($_FILES["dealImage"]["tmp_name"], "components/com_deals/dealImages/" .$id."_".$_FILES["dealImage"]["name"]);
echo "Stored in: " . "dealImages/" . $_FILES["dealImage"]["name"];
}
}
}
else
{
}
}
$dealImage = $_FILES['dealImage']['name'];
$dealImage .= (!empty($_FILES['dealImage']['name'])) ? ' ' . $_FILES['dealImage']['name'] : '';
$query = "UPDATE #__todaysdeal SET dealImage='".$id."_".$_FILES['dealImage']['name']."' WHERE id='".$id."'";
$db = $this->getDBO();
$db->setQuery($query);
$db->query();
//If we get here and with no raiseErrors, then everythign went well
}
function deleteDeals($arrayIDs)
{
$query = "DELETE FROM #__todaysdeal WHERE id IN (".implode(',', $arrayIDs).")";
$db = $this->getDBO();
$db->setQuery($query);
if (!$db->query()){
$errorMessage = $this->getDBO()->getErrorMsg();
JError::raiseError(500, 'Error deleting Deals: '.$errorMessage);
}
}
function dealsUploadPhoto($file, $id)
{
//UPLOAD FILE
$config = & JComponentHelper::getParams('com_deals');
$allowed = array('image/pjpeg', 'image/jpeg', 'image/jpg', 'image/png', 'image/x-png', 'image/gif', 'image/ico', 'image/x-icon');
$pwidth = $config->get('pwidth');
$pheight = $config->get('pheight');
$maxsize = $config->get('maxsize');
if($file['size'] > 0 && ($file['size'] / 1024 < $maxsize)){
if(!file_exists(JPATH_SITE . DS. 'images' . DS . 'deals'))
{
if(mkdir(JPATH_SITE . DS . 'images' . DS . 'deals')) {
JPath::setPermissions(JPATH_SITE . DS . 'images' . DS . 'deals', '0777');
if(file_exists(JPATH_SITE . DS . 'images' . DS . 'index.html')) {
copy(JPATH_SITE . DS . 'images' . DS . 'index.html', JPATH_SITE . DS . 'images' . DS . 'deals/index.html');
}
}
}
if($file['error'] != 0){
tpJobsMsgAlert('Upload file photo error.');
exit ();
}
if($file['size'] == 0){
$file = null;
}
if(!in_array($file['type'], $allowed)) {
$file = null;
}
if ($file != null){
$dest = JPATH_SITE.DS.'images'.DS.'deals'.DS.$id.'.jpg';
if(file_exists($dest))
{
$del = unlink($dest);
}
$soure = $file['tmp_name'];
jimport('joomla.filesystem.file');
$uploaded = JFile::upload($soure,$dest);
$fileAtr = getimagesize($dest);
$widthOri = $fileAtr[0];
$heightOri = $fileAtr[1];
$type = $fileAtr['mime'];
$img = false;
switch ($type)
{
case 'image/jpeg':
case 'image/jpg':
case 'image/pjpeg':
$img = imagecreatefromjpeg($dest);
break;
case 'image/ico':
$img = imagecreatefromico($dest);
break;
case 'image/x-png':
case 'image/png':
$img = imagecreatefrompng($dest);
break;
case 'image/gif':
$img = imagecreatefromgif($dest);
break;
}
if(!$img)
{
return false;
}
$curr = #getimagesize($dest);
$perc_w = $pwidth / $widthOri;
$perc_h = $pheight / $heightOri;
if(($widthOri<$pwidth) && ($heightOri<$height))
{
return;
}
if($perc_h > $perc_w)
{
$pwidth = $pwidth;
$pheight = round($heightOri * $perc_w);
}
else
{
$pheight = $pheight;
$pwidth = round($widthOri * $perc_h);
}
$nwimg = imagecreatetruecolor($pwidth, $pheight);
imagecopyresampled($nwimg, $img, 0, 0, 0, 0, $pwidth, $pheight, $widthOri, $heightOri);
imagejpeg($nwimg, $dest, 100);
imagedestroy($nwimg);
imagedestroy($img);
}
}else{
if($file['size'] / 1024 > $maxsize){
dealsMsgAlert('Size of file photo is too big. Maximum size".$maxsize." KB');
exit ();
}
}
}
function dealsMsgAlert($msg)
{
if (!headers_sent())
{
while(#ob_end_clean());
ob_start();
echo "<script> alert('".$msg."'); window.history.go(-1); </script>\n";
$out = ob_get_contents();
ob_end_clean();
echo $out;
exit();
}
echo "<script> alert('".$msg."'); window.history.go(-1); </script>\n";
exit();
}
}
?>
The problem that causes the red screen with 500 Error is happening because you are raising an exception if the requested quote is does not exist. You should not use JError::raiseError().
Use one of the following instead:
// This will set error to the model. You can get the errors from
// the model by your controller $model->getErrors() and output them to the screen.
$this->setError('ERROR MESSAGE GOES HERE');
OR
// This will output errors to the screen right the way
JFactory::getApplication()->enqueueMessage('ERROR MESSAGE GOES HERE', 'message');
Model already has _db property, you do not need to get db into variable. You can access it like this $this->_db. You can read about Joomla Model class here.
Also within your model you are using
$db = $this->getDBO();
$db->setQuery('SELECT * from #__todaysdeal');
$deals = $db->loadObjectList();
Model has simplified method to load list of object, like so
$deals =& $this->_getList('SELECT * from #__todaysdeal');