Related
so I set up a ticketing system called osticket for our users, unfortunately they do not have an automated workflow feature. Basically what I would like for the ticketing system to do is create an automated child task from a parent ticket. So if someone puts in a software request, then a parent request is created for support team and an approval child task is automatically created and assigned to management. I have no idea where to begin since I do not have a thorough programming background. If someone can point me to the direction of where I can find information about something similar or just provide a guide, that would be great!
Below is the current configured task.php file
<?php
/*********************************************************************
class.task.php
**********************************************************************/
include_once INCLUDE_DIR.'class.role.php';
class TaskModel extends VerySimpleModel {
static $meta = array(
'table' => TASK_TABLE,
'pk' => array('id'),
'joins' => array(
'dept' => array(
'constraint' => array('dept_id' => 'Dept.id'),
),
'lock' => array(
'constraint' => array('lock_id' => 'Lock.lock_id'),
'null' => true,
),
'staff' => array(
'constraint' => array('staff_id' => 'Staff.staff_id'),
'null' => true,
),
'team' => array(
'constraint' => array('team_id' => 'Team.team_id'),
'null' => true,
),
'thread' => array(
'constraint' => array(
'id' => 'TaskThread.object_id',
"'A'" => 'TaskThread.object_type',
),
'list' => false,
'null' => false,
),
'cdata' => array(
'constraint' => array('id' => 'TaskCData.task_id'),
"class.task.php" 1826 lines, 57620 characters
If I can provide any additional information, then please let me know.
Edit
Managed to find this php file, towards the bottom it mentions something about "Create Task", I'm guessing this is where I'll have the ability to set up an automated feature?
<?php
/*********************************************************************
class.thread_actions.php
Actions for thread entries. This serves as a simple repository for
drop-down actions which can be triggered on the ticket-view page for an
object's thread.
Jared Hancock <jared#osticket.com>
Peter Rotich <peter#osticket.com>
Copyright (c) 2006-2014 osTicket
http://www.osticket.com
Released under the GNU General Public License WITHOUT ANY WARRANTY.
See LICENSE.TXT for details.
vim: expandtab sw=4 ts=4 sts=4:
**********************************************************************/
include_once(INCLUDE_DIR.'class.thread.php');
class TEA_ShowEmailRecipients extends ThreadEntryAction {
static $id = 'emailrecipients';
static $name = /* trans */ 'View Email Recipients';
static $icon = 'group';
function isVisible() {
global $thisstaff;
if ($this->entry->getEmailHeader())
return ($thisstaff && $this->entry->getEmailHeader());
elseif ($this->entry->recipients)
return $this->entry->recipients;
}
function getJsStub() {
return sprintf("$.dialog('%s');",
$this->getAjaxUrl()
);
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET' && $this->entry->recipients:
return $this->getRecipients();
case 'GET':
return $this->trigger__get();
}
}
private function trigger__get() {
$hdr = Mail_parse::splitHeaders(
$this->entry->getEmailHeader(), true);
$recipients = array();
foreach (array('To', 'TO', 'Cc', 'CC') as $k) {
if (isset($hdr[$k]) && $hdr[$k] &&
($addresses=Mail_Parse::parseAddressList($hdr[$k]))) {
foreach ($addresses as $addr) {
$email = sprintf('%s#%s', $addr->mailbox, $addr->host);
$name = $addr->personal ?: '';
$recipients[$k][] = sprintf('%s<%s>',
(($name && strcasecmp($name, $email))? "$name ": ''),
$email);
}
}
}
include STAFFINC_DIR . 'templates/thread-email-recipients.tmpl.php';
}
private function getRecipients() {
$recipients = json_decode($this->entry->recipients, true);
include STAFFINC_DIR . 'templates/thread-email-recipients.tmpl.php';
}
}
ThreadEntry::registerAction(/* trans */ 'E-Mail', 'TEA_ShowEmailRecipients');
class TEA_ShowEmailHeaders extends ThreadEntryAction {
static $id = 'view_headers';
static $name = /* trans */ 'View Email Headers';
static $icon = 'envelope';
function isVisible() {
global $thisstaff;
if (!$this->entry->getEmailHeader())
return false;
return $thisstaff && $thisstaff->isAdmin();
}
function getJsStub() {
return sprintf("$.dialog('%s');",
$this->getAjaxUrl()
);
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
return $this->trigger__get();
}
}
private function trigger__get() {
$headers = $this->entry->getEmailHeader();
include STAFFINC_DIR . 'templates/thread-email-headers.tmpl.php';
}
}
ThreadEntry::registerAction(/* trans */ 'E-Mail', 'TEA_ShowEmailHeaders');
class TEA_EditThreadEntry extends ThreadEntryAction {
static $id = 'edit';
static $name = /* trans */ 'Edit';
static $icon = 'pencil';
function isVisible() {
// Can't edit system posts
return ($this->entry->staff_id || $this->entry->user_id)
&& $this->entry->type != 'R' && $this->isEnabled();
}
function isEnabled() {
global $thisstaff;
$T = $this->entry->getThread()->getObject();
// You can edit your own posts or posts by your department members
// if your a manager, or everyone's if your an admin
return $thisstaff && (
$thisstaff->getId() == $this->entry->staff_id
|| ($T instanceof Ticket
&& $T->getDept()->getManagerId() == $thisstaff->getId()
)
|| ($T instanceof Ticket
&& ($role = $thisstaff->getRole($T->getDeptId(), $T->isAssigned($thisstaff)))
&& $role->hasPerm(ThreadEntry::PERM_EDIT)
)
|| ($T instanceof Task
&& $T->getDept()->getManagerId() == $thisstaff->getId()
)
|| ($T instanceof Task
&& ($role = $thisstaff->getRole($T->getDeptId(), $T->isAssigned($thisstaff)))
&& $role->hasPerm(ThreadEntry::PERM_EDIT)
)
);
}
function getJsStub() {
return sprintf(<<<JS
var url = '%s';
$.dialog(url, [201], function(xhr, resp) {
var json = JSON.parse(resp);
if (!json || !json.thread_id)
return;
$('#thread-entry-'+json.thread_id)
.attr('id', 'thread-entry-' + json.new_id)
.html(json.entry)
.find('.thread-body')
.delay(500)
.effect('highlight');
}, {size:'large'});
JS
, $this->getAjaxUrl());
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
return $this->trigger__get();
case 'POST':
return $this->trigger__post();
}
}
protected function trigger__get() {
global $cfg, $thisstaff;
$poster = $this->entry->getStaff();
include STAFFINC_DIR . 'templates/thread-entry-edit.tmpl.php';
}
function updateEntry($guard=false) {
global $thisstaff;
$old = $this->entry;
$new = ThreadEntryBody::fromFormattedText($_POST['body'], $old->format);
if ($new->getClean() == $old->getBody())
// No update was performed
return $old;
$entry = ThreadEntry::create(array(
// Copy most information from the old entry
'poster' => $old->poster,
'userId' => $old->user_id,
'staffId' => $old->staff_id,
'type' => $old->type,
'threadId' => $old->thread_id,
'recipients' => $old->recipients,
// Connect the new entry to be a child of the previous
'pid' => $old->id,
// Add in new stuff
'title' => Format::htmlchars($_POST['title']),
'body' => $new,
'ip_address' => $_SERVER['REMOTE_ADDR'],
));
if (!$entry)
return false;
// Move the attachments to the new entry
$old->attachments->filter(array(
'inline' => false,
))->update(array(
'object_id' => $entry->id
));
// Note, anything that points to the $old entry as PID should remain
// that way for email header lookups and such to remain consistent
if ($old->flags & ThreadEntry::FLAG_EDITED
// If editing another person's edit, make a new entry
and ($old->editor == $thisstaff->getId() && $old->editor_type == 'S')
and !($old->flags & ThreadEntry::FLAG_GUARDED)
) {
// Replace previous edit --------------------------
$original = $old->getParent();
// Link the new entry to the old id
$entry->pid = $old->pid;
// Drop the previous edit, and base this edit off the original
$old->delete();
$old = $original;
}
// Mark the new entry as edited (but not hidden nor guarded)
$entry->flags = ($old->flags & ~(ThreadEntry::FLAG_HIDDEN | ThreadEntry::FLAG_GUARDED))
| ThreadEntry::FLAG_EDITED;
// Guard against deletes on future edit if requested. This is done
// if an email was triggered by the last edit. In such a case, it
// should not be replaced by a subsequent edit.
if ($guard)
$entry->flags |= ThreadEntry::FLAG_GUARDED;
// Log the editor
$entry->editor = $thisstaff->getId();
$entry->editor_type = 'S';
// Sort in the same place in the thread
$entry->created = $old->created;
$entry->updated = SqlFunction::NOW();
$entry->save(true);
// Hide the old entry from the object thread
$old->flags |= ThreadEntry::FLAG_HIDDEN;
$old->save();
return $entry;
}
protected function trigger__post() {
global $thisstaff;
if (!($entry = $this->updateEntry()))
return $this->trigger__get();
ob_start();
include STAFFINC_DIR . 'templates/thread-entry.tmpl.php';
$content = ob_get_clean();
Http::response('201', JsonDataEncoder::encode(array(
'thread_id' => $this->entry->id, # This is the old id!
'new_id' => $entry->id,
'entry' => $content,
)));
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_EditThreadEntry');
class TEA_OrigThreadEntry extends ThreadEntryAction {
static $id = 'previous';
static $name = /* trans */ 'View History';
static $icon = 'copy';
function isVisible() {
// Can't edit system posts
return $this->entry->flags & ThreadEntry::FLAG_EDITED;
}
function getJsStub() {
return sprintf("$.dialog('%s');",
$this->getAjaxUrl()
);
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
return $this->trigger__get();
}
}
private function trigger__get() {
global $thisstaff;
if (!$this->entry->getParent())
Http::response(404, 'No history for this entry');
$entry = $this->entry;
include STAFFINC_DIR . 'templates/thread-entry-view.tmpl.php';
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_OrigThreadEntry');
class TEA_EditAndResendThreadEntry extends TEA_EditThreadEntry {
static $id = 'edit_resend';
static $name = /* trans */ 'Edit and Resend';
static $icon = 'reply-all';
function isVisible() {
// Can only resend replies
return $this->entry->staff_id && $this->entry->type == 'R'
&& $this->isEnabled();
}
protected function trigger__post() {
$resend = #$_POST['commit'] == 'resend';
if (!($entry = $this->updateEntry($resend)))
return $this->trigger__get();
if ($resend)
$this->resend($entry);
ob_start();
include STAFFINC_DIR . 'templates/thread-entry.tmpl.php';
$content = ob_get_clean();
Http::response('201', JsonDataEncoder::encode(array(
'thread_id' => $this->entry->id, # This is the old id!
'new_id' => $entry->id,
'entry' => $content,
)));
}
function resend($response) {
global $cfg, $thisstaff;
if (!($object = $response->getThread()->getObject()))
return false;
$vars = $_POST;
$dept = $object->getDept();
$poster = $response->getStaff();
if ($thisstaff && $vars['signature'] == 'mine')
$signature = $thisstaff->getSignature();
elseif ($poster && $vars['signature'] == 'theirs')
$signature = $poster->getSignature();
elseif ($vars['signature'] == 'dept' && $dept && $dept->isPublic())
$signature = $dept->getSignature();
else
$signature = '';
$variables = array(
'response' => $response,
'signature' => $signature,
'staff' => $response->getStaff(),
'poster' => $response->getStaff());
$options = array('thread' => $response);
// Resend response to collabs
if (($object instanceof Ticket)
&& ($email=$dept->getEmail())
&& ($tpl = $dept->getTemplate())
&& ($msg=$tpl->getReplyMsgTemplate())) {
$recipients = json_decode($response->recipients, true);
$msg = $object->replaceVars($msg->asArray(),
$variables + array('recipient' => $object->getOwner()));
$attachments = $cfg->emailAttachments()
? $response->getAttachments() : array();
$email->send($object->getOwner(), $msg['subj'], $msg['body'],
$attachments, $options, $recipients);
}
// TODO: Add an option to the dialog
if ($object instanceof Task)
$object->notifyCollaborators($response, array('signature' => $signature));
// Log an event that the item was resent
$object->logEvent('resent', array('entry' => $response->id));
$type = array('type' => 'resent');
Signal::send('object.edited', $object, $type);
// Flag the entry as resent
$response->flags |= ThreadEntry::FLAG_RESENT;
$response->save();
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_EditAndResendThreadEntry');
class TEA_ResendThreadEntry extends TEA_EditAndResendThreadEntry {
static $id = 'resend';
static $name = /* trans */ 'Resend';
static $icon = 'reply-all';
function isVisible() {
// Can only resend replies
return $this->entry->staff_id && $this->entry->type == 'R'
&& !parent::isEnabled();
}
function isEnabled() {
return true;
}
protected function trigger__get() {
global $cfg, $thisstaff;
$poster = $this->entry->getStaff();
include STAFFINC_DIR . 'templates/thread-entry-resend.tmpl.php';
}
protected function trigger__post() {
$resend = #$_POST['commit'] == 'resend';
if (#$_POST['commit'] == 'resend')
$this->resend($this->entry);
Http::response('201', 'Okee dokey');
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_ResendThreadEntry');
/* Create a new ticket from thread entry as description */
class TEA_CreateTicket extends ThreadEntryAction {
static $id = 'create_ticket';
static $name = /* trans */ 'Create Ticket';
static $icon = 'plus';
function isVisible() {
global $thisstaff;
return $thisstaff && $thisstaff->hasPerm(Ticket::PERM_CREATE, false);
}
function getJsStub() {
return sprintf(<<<JS
window.location.href = '%s';
JS
, $this->getCreateTicketUrl()
);
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
return $this->trigger__get();
}
}
private function trigger__get() {
Http::redirect($this->getCreateTicketUrl());
}
private function getCreateTicketUrl() {
return sprintf('tickets.php?a=open&tid=%d', $this->entry->getId());
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_CreateTicket');
class TEA_CreateTask extends ThreadEntryAction {
static $id = 'create_task';
static $name = /* trans */ 'Create Task';
static $icon = 'plus';
function isVisible() {
global $thisstaff;
return $thisstaff && $thisstaff->hasPerm(Task::PERM_CREATE, false);
}
function getJsStub() {
return sprintf(<<<JS
var url = '%s';
var redirect = $(this).data('redirect');
$.dialog(url, [201], function(xhr, resp) {
if (!!redirect)
$.pjax({url: redirect, container: '#pjax-container'});
else
$.pjax({url: '%s.php?id=%d#tasks', container: '#pjax-container'});
});
JS
, $this->getAjaxUrl(),
$this->entry->getThread()->getObjectType() == 'T' ? 'tickets' : 'tasks',
$this->entry->getThread()->getObjectId()
);
}
function trigger() {
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
return $this->trigger__get();
case 'POST':
return $this->trigger__post();
}
}
private function trigger__get() {
$vars = array(
'description' => Format::htmlchars($this->entry->getBody()));
if ($_SESSION[':form-data'])
unset($_SESSION[':form-data']);
$_SESSION[':form-data']['tid'] = $this->entry->getThread()->getObJectId();
$_SESSION[':form-data']['eid'] = $this->entry->getId();
$_SESSION[':form-data']['timestamp'] = $this->entry->getCreateDate();
$_SESSION[':form-data']['type'] = $this->entry->getThread()->object_type;
if (($f= TaskForm::getInstance()->getField('description'))) {
$k = 'attach:'.$f->getId();
unset($_SESSION[':form-data'][$k]);
foreach ($this->entry->getAttachments() as $a)
if (!$a->inline && $a->file) {
$_SESSION[':form-data'][$k][$a->file->getId()] = $a->getFilename();
$_SESSION[':uploadedFiles'][$a->file->getId()] = $a->getFilename();
}
}
if ($this->entry->getThread()->getObjectType() == 'T')
return $this->getTicketsAPI()->addTask($this->getObjectId(), $vars);
else
return $this->getTasksAPI()->add($this->getObjectId(), $vars);
}
private function trigger__post() {
if ($this->entry->getThread()->getObjectType() == 'T')
return $this->getTicketsAPI()->addTask($this->getObjectId());
else
return $this->getTasksAPI()->add($this->getObjectId());
}
}
ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_CreateTask');
I am having some trouble, mostly from the lack of my knowledge on WordPress and I need some expert help. I am retrieving data from a table named wp_words in my WordPress database, and I am showing them in a table form, in a menu page in the WordPress administrator panel. I create a menu page called Lexicon Testing and the table is shown in that menu page. What I want to do is, when I click the edit button below each code (as shown in the picture), to be able to edit the rest of the lines fields on the same page. Like a quick edit function like in posts and pages. The way that I am retrieving data is shown n the code below. I would like some advice please and some guidance. Is it possible to do it like I want? Do I need to retrieve data another way to make it work like that? The way I used to retrieve data is on this page: https://www.sitepoint.com/using-wp_list_table-to-create-wordpress-admin-tables/
<?php
/*
Plugin Name: Testing v1
Description: Testing
Version: 1.0
*/
if (!class_exists('WP_List_Table')) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class Lexicon_words_List extends WP_List_Table {
/** Class constructor */
public function __construct() {
parent::__construct([
'singular' => __('Lexicon word', 'sp'), //singular name of the listed records
'plural' => __('Lexicon words', 'sp'), //plural name of the listed records
'ajax' => false //does this table support ajax?
]);
}
/**
* Retrieve customers data from the database
*
* #param int $per_page
* #param int $page_number
*
* #return mixed
*/
public static function get_lexicon_words($per_page = 5, $page_number = 1) {
global $wpdb;
$sql = "SELECT * FROM {$wpdb->prefix}lexicon_words";
if (!empty($_REQUEST['orderby'])) {
$sql .= ' ORDER BY ' . esc_sql($_REQUEST['orderby']);
$sql .= !empty($_REQUEST['order']) ? ' ' . esc_sql($_REQUEST['order']) : ' ASC';
}
$sql .= " LIMIT $per_page";
$sql .= ' OFFSET ' . ( $page_number - 1 ) * $per_page;
$result = $wpdb->get_results($sql, 'ARRAY_A');
return $result;
}
/**
* Delete a customer record.
*
* #param int $id customer ID
*/
public static function delete_lexicon_word($id) {
global $wpdb;
$wpdb->delete(
"{$wpdb->prefix}lexicon_words", array('id' => $id)
);
}
/**
* Edit a customer record.
*
* #param int $id customer ID
*/
public static function edit_lexicon_word($id) {
}
/**
* Returns the count of records in the database.
*
* #return null|string
*/
public static function record_count() {
global $wpdb;
$sql = "SELECT COUNT(*) FROM {$wpdb->prefix}lexicon_words";
return $wpdb->get_var($sql);
}
/** Text displayed when no customer data is available */
public function no_items() {
_e('No words avaliable.', 'sp');
}
/**
* Render a column when no column specific method exist.
*
* #param array $item
* #param string $column_name
*
* #return mixed
*/
public function column_default($item, $column_name) {
switch ($column_name) {
case 'code':
case 'text':
case 'phrase':
case 'context':
case 'level':
case 'lang':
return $item[$column_name];
default:
return print_r($item, true); //Show the whole array for troubleshooting purposes
}
}
/**
* Render the bulk edit checkbox
*
* #param array $item
*
* #return string
*/
function column_cb($item) {
return sprintf(
'<input type="checkbox" name="bulk-delete[]" value="%s" />', $item['id']
);
}
/**
* Method for code column
*
* #param array $item an array of DB data
*
* #return string
*/
function column_code($item) {
$delete_nonce = wp_create_nonce('sp_delete_lexicon_word');
$edit_nonce = wp_create_nonce('sp_edit_lexicon_word');
$title = '<strong>' . $item['code'] . '</strong>';
$actions = [
'edit' => sprintf('Edit', esc_attr($_REQUEST['page']), 'edit', absint($item['id']), $edit_nonce),
'delete' => sprintf('Delete', esc_attr($_REQUEST['page']), 'delete', absint($item['id']), $delete_nonce)
];
return $title . $this->row_actions($actions);
}
/**
* Associative array of columns
*
* #return array
*/
function get_columns() {
$columns = [
'cb' => '<input type="checkbox" />',
'code' => __('Code', 'sp'),
'text' => __('Text', 'sp'),
'phrase' => __('Phrase', 'sp'),
'context' => __('Context', 'sp'),
'level' => __('Level', 'sp'),
'column_6' => __('Column 6', 'sp'),
'column_7' => __('Column 7', 'sp'),
'column_8' => __('Column 8', 'sp'),
'column_9' => __('Column 9', 'sp'),
'column_10' => __('Column 10', 'sp'),
'column_11' => __('Column 11', 'sp'),
'column_12' => __('Column 12', 'sp'),
'column_13' => __('Column 13', 'sp'),
'column_14' => __('Column 14', 'sp'),
'column_15' => __('Column 15', 'sp'),
'column_16' => __('Column 16', 'sp'),
'lang' => __('Lang', 'sp')
];
return $columns;
}
/**
* Columns to make sortable.
*
* #return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'code' => array('code', true),
'text' => array('text', false)
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* #return array
*/
public function get_bulk_actions() {
$actions = [
'bulk-delete' => 'Delete'
];
return $actions;
}
/**
* Handles data query and filter, sorting, and pagination.
*/
public function prepare_items() {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
$per_page = $this->get_items_per_page('lexicon_words_per_page', 5);
$current_page = $this->get_pagenum();
$total_items = self::record_count();
$this->set_pagination_args([
'total_items' => $total_items, //WE have to calculate the total number of items
'per_page' => $per_page //WE have to determine how many items to show on a page
]);
$this->items = self::get_lexicon_words($per_page, $current_page);
}
public function process_bulk_action() {
//Detect when a bulk action is being triggered...
if ('delete' === $this->current_action()) {
// In our file that handles the request, verify the nonce.
$nonce = esc_attr($_REQUEST['_wpnonce']);
if (!wp_verify_nonce($nonce, 'sp_delete_lexicon_word')) {
die('Fatal Error');
} else {
self::delete_lexicon_word(absint($_GET['lexicon_word']));
// esc_url_raw() is used to prevent converting ampersand in url to "#038;"
// add_query_arg() return the current url
//$origUrl = esc_attr($_REQUEST['page']);
wp_redirect(esc_url_raw(add_query_arg(array('page' => 'lexicon_testing'), admin_url('admin.php'))));
exit;
}
}
if ('edit' === $this->current_action()) {
// In our file that handles the request, verify the nonce.
$nonce = esc_attr($_REQUEST['_wpnonce']);
if (!wp_verify_nonce($nonce, 'sp_edit_lexicon_word')) {
die('Fatal Error');
} else {
self::edit_lexicon_word(absint($_GET['lexicon_word']));
// esc_url_raw() is used to prevent converting ampersand in url to "#038;"
// add_query_arg() return the current url
//$origUrl = esc_attr($_REQUEST['page']);
wp_redirect(esc_url_raw(add_query_arg(array('page' => 'lexicon_testing'), admin_url('admin.php'))));
exit;
}
}
// If the delete bulk action is triggered
if (( isset($_POST['action']) && $_POST['action'] == 'bulk-delete' ) || ( isset($_POST['action2']) && $_POST['action2'] == 'bulk-delete' )
) {
$delete_ids = esc_sql($_POST['bulk-delete']);
// loop over the array of record IDs and delete them
foreach ($delete_ids as $id) {
self::delete_lexicon_word($id);
}
// esc_url_raw() is used to prevent converting ampersand in url to "#038;"
// add_query_arg() return the current url
wp_redirect(esc_url_raw(add_query_arg(array('page' => 'lexicon_testing'), admin_url('admin.php'))));
exit;
}
}
}
class SP_Plugin {
// class instance
static $instance;
// customer WP_List_Table object
public $lexicon_words_obj;
// class constructor
public function __construct() {
add_filter('set-screen-option', [__CLASS__, 'set_screen'], 10, 3);
add_action('admin_menu', [$this, 'plugin_menu']);
}
public static function set_screen($status, $option, $value) {
return $value;
}
public function plugin_menu() {
$hook = add_menu_page(
'Lexicon Testing', 'Lexicon Testing', 'manage_options', 'lexicon_testing', [$this, 'plugin_settings_page']
);
add_action("load-$hook", [$this, 'screen_option']);
}
/**
* Plugin settings page
*/
public function plugin_settings_page() {
?>
<div class="wrap">
<h2>Lexicon Database Management</h2>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="post">
<?php
$this->lexicon_words_obj->prepare_items();
$this->lexicon_words_obj->display();
?>
</form>
</div>
</div>
</div>
<br class="clear">
</div>
</div>
<?php
}
/**
* Screen options
*/
public function screen_option() {
$option = 'per_page';
$args = [
'label' => 'Words',
'default' => 5,
'option' => 'lexicon_words_per_page'
];
add_screen_option($option, $args);
$this->lexicon_words_obj = new Lexicon_words_List();
}
/** Singleton instance */
public static function get_instance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
function edit_word_metabox() {
add_meta_box('editword_metabox', '$title', 'editword_metabox_callback', 'lexicon_testing');
}
function editword_metabox_callback() {
}
}
add_action('plugins_loaded', function () {
SP_Plugin::get_instance();
});
I am having an issue with a cakephp script. It was written with cakephp version 2.5.1.
I'm getting fatal error: Fatal error: Cannot call constructor in /lib/Cake/Controller/CakeErrorController.php on line 46.
The original AppController.php file looked like this:
<?php
if (session_id() == '') {
session_start();
}
class AppController
{
public $components = array('Auth');
public $helpers = array(
0 => 'Form',
'Html' => array('className' => 'MyHtml')
);
public function beforeFilter()
{
global $loguser;
global $username;
global $siteChanges;
global $paypalAdaptive;
global $user_level;
global $setngs;
global $price;
global $colors;
global $parent_categori;
global $googlecode;
parent::beforeFilter();
$this->Auth->loginAction = array('controller' => '/', 'action' => '/login');
$this->Auth->logoutRedirect = array('controller' => '/', 'action' => '/');
$this->Auth->authenticate = array(
AuthComponent::ALL => array(
'fields' => array('username' => 'email', 'password' => 'password'),
'userModel' => 'Users.User'
),
0 => 'Form'
);
if ($this->params['controller'] == 'api') {
$this->Auth->allow();
}
if ($this->params['controller'] == 'fantasyhelps') {
$this->Auth->allow();
}
if ($this->params['controller'] == 'paypals') {
App::import('Vendor', 'PayPal');
}
$this->Auth->allow(, , 'login', 'signup', 'emailverification', 'verification', 'index', 'setpassword', 'userprofiles', 'viewshops', 'addto', 'press', 'about', 'toppeople', 'findpeople', 'storeprofiles', 'getstoreprofile', 'listings', 'show_color', 'show_price', 'showByCategory', 'getMorePosts', 'ipnprocess', 'getmorepricecolor', 'getItemByCategory', 'ajaxSearch', 'captcha', 'forgotpassword', 'showByRelation', 'getItemByRelation', 'faq', 'contact', 'item_comments', 'changePassword', 'copyrights', 'termsofsale', 'termsofservice', 'termsofmerchant', 'privacy', 'loginwith', 'loginwithtwitter', 'changecurrency', 'downimage', 'sitemaintenance', 'getviewmore', 'customviewmore', 'orderstatus', 'getsizeqty', 'searches', 'getmoregallery', 'viewitemdesc', 'followersList', 'getmoreprofile', 'getmorestorycomment', 'followingList', 'twittlogin_save', 'item_favorited', 'merupdate', 'custupdatend', 'testing', 'bookmarklet', 'getmorecomments', 'adaptiveipnprocess', 'additemusingurl', 'giftcardipnIpn', 'ggipn', 'ggcronjob', 'nearme', 'getMorenearme', 'gifts', 'story');
$loguser = $this->Auth->user();
$userid = $loguser[0]['User']['id'];
$username = $loguser[0]['User']['username'];
$first_name = $loguser[0]['User']['first_name'];
$username_url = $loguser[0]['User']['username_url'];
$user_level = $loguser[0]['User']['user_level'];
$profile_image = $loguser[0]['User']['profile_image'];
$this->set('loguser', $loguser);
$this->set('username', $username);
$this->set('username_url', $username_url);
$this->set('user_level', $user_level);
$this->set('first_name', $first_name);
$this->set('profile_image', $profile_image);
$this->set('currentaction', $this->params['action']);
$this->loadModel('User');
$user_datas = $this->User->findById($userid);
if (!empty($loguser) && empty($user_datas)) {
$this->Auth->logout();
}
$user_status_val = $this->User->find('first', array(
'conditions' => array('User.id' => $userid)
));
$user_status = $user_status_val['User']['user_status'];
if ($user_status == 'disable') {
$this->Session->setFlash(__('Your account has been disabled please contact our support'), 'default', array(), 'bad');
$this->redirect($this->Auth->logout());
$this->redirect('/login');
}
$this->loadModel('Sitesetting');
$this->loadModel('Cart');
$this->loadModel('Orders');
$this->loadModel('Item');
$this->loadModel('Price');
$this->loadModel('Color');
$this->loadModel('Category');
$this->loadModel('Forexrate');
$this->loadModel('Managemodule');
$this->loadModel('Googlecode');
$this->loadModel('Contactseller');
$this->loadModel('Story');
$orderdetails = $this->Orders->find('all', array(
'conditions' => array('Orders.merchant_id' => $userid)
));
$this->set('orderdetails', $orderdetails);
$storyCount = $this->Story->find('count', array(
'conditions' => array('userid' => $userid)
));
$this->set('storyCounts', $storyCount);
$managemoduleModel = $this->Managemodule->find('first');
$this->set('managemoduleModel', $managemoduleModel);
$params = $this->params;
$action = $params['action'];
if ($this->params['controller'] != 'api') {
$this->_setLanguage();
}
if (($action != 'sitemaintenance') && ($action != 'login') && ($this->params['controller'] != 'api')) {
if (!$this->isauthenticated() || ($user_level != 'god')) {
if ($managemoduleModel['Managemodule']['site_maintenance_mode'] == 'yes') {
$this->redirect('/sitemaintenance');
}
}
}
$messageCount = $this->Contactseller->find('count', array(
'conditions' => array(
'OR' => array(
array('merchantid' => $userid, 'sellerread' => 1),
array('buyerid' => $userid, 'buyerread' => 1)
)
)
));
$_SESSION['userMessageCount'] = $messageCount;
if (!isset($_SESSION['language_settings'])) {
$languageJson = file_get_contents(SITE_URL . 'language_settings.json');
$_SESSION['language_settings'] = json_decode($languageJson, true);
$defaultLanguage = $_SESSION['language_settings']['settings']['default'];
Configure::write('Config.language', $defaultLanguage);
}
if (!isset($_SESSION['currency_value'])) {
$forexrateModel = $this->Forexrate->find('first', array(
'conditions' => array('status' => 'default')
));
$_SESSION['currency_symbol'] = $forexrateModel['Forexrate']['currency_symbol'];
$_SESSION['currency_value'] = $forexrateModel['Forexrate']['price'];
$_SESSION['currency_code'] = $forexrateModel['Forexrate']['currency_code'];
$_SESSION['default_currency_code'] = $forexrateModel['Forexrate']['currency_code'];
$_SESSION['default_currency_symbol'] = $forexrateModel['Forexrate']['currency_symbol'];
}
$setngs = $this->Sitesetting->find('all');
$price = ('all');
$forexrateModel = $this->Forexrate->find('all', array(
'conditions' => array('status <>' => 'disable')
));
$colors = $this->Color->find('all');
$UserDetailss = $this->User->findById($userid);
$this->set('UserDetailss', $UserDetailss);
$this->loadModel('Shop');
$sellerDetails = $this->Shop->find('all', array(
'conditions' => array('user_id' => $userid)
));
$this->set('sellerDetails', $sellerDetails);
$shopDetails = $this->Shop->find('first', array(
'conditions' => array('user_id' => $userid)
));
$this->set('shop_name', $shopDetails['Shop']['shop_name']);
$parent_categori = $this->Category->find('all', array(
'conditions' => array('category_parent' => 0)
));
$googlecode = $this->Googlecode->find('all');
if (!empty($userid)) {
if (!empty($carts)) {
foreach ($carts as $crt) {
$itmids[] = $crt['Cart']['item_id'];
}
$itm_datas = $this->Item->find('all', array(
'conditions' => array('Item.id' => $itmids, 'Item.status' => 'publish')
));
$total_itms = count($itm_datas);
$this->set('total_itms', $total_itms);
}
}
$this->set('price', $price);
$this->set('colors', $colors);
$this->set('forexrateModel', $forexrateModel);
$this->set('parent_categori', $parent_categori);
$this->set('googlecode', $googlecode);
$this->set('media_url', $setngs[0]['Sitesetting']['media_url']);
$this->set('setngs', $setngs);
$siteChanges = $setngs[0]['Sitesetting']['site_changes'];
$siteChanges = json_decode($siteChanges, true);
$paypalAdaptive = $setngs[0]['Sitesetting']['paypaladaptive'];
$paypalAdaptive = json_decode($paypalAdaptive, true);
$this->set('siteChanges', $siteChanges);
$_SESSION['site_url'] = SITE_URL;
$_SESSION['media_url'] = SITE_URL;
if (!empty($setngs[0]['Sitesetting']['media_url'])) {
$_SESSION['media_host_name'] = $setngs[0]['Sitesetting']['media_server_hostname'];
$_SESSION['media_url'] = $setngs[0]['Sitesetting']['media_url'];
$_SESSION['media_server_username'] = $setngs[0]['Sitesetting']['media_server_username'];
$_SESSION['media_server_password'] = $setngs[0]['Sitesetting']['media_server_password'];
}
$params = $this->params;
$action = $params['action'];
$this->set('action', $action);
if ($this->params['controller'] != 'api') {
$this->_setLanguage();
}
}
public function isauthenticated()
{
$user = $this->Auth->user();
if (!empty($user)) {
return true;
}
return false;
}
public function isauthorized()
{
$user = $this->Auth->user();
if (($user[0]['User']['user_level'] == 'god') || ($user[0]['User']['user_level'] == 'moderator')) {
return true;
}
return false;
}
public function isauthorizedpersn()
{
$user = ();
if (($user[0]['User']['user_level'] == 'god') || ($user[0]['User']['user_level'] == 'shop')) {
return true;
}
return false;
}
public function _setLanguage()
{
if (isset($this->Cookie) && $this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
$this->Session->write('Config.language', $this->Cookie->read('lang'));
}
else if (isset($this->params['language']) && ($this->params['language'] != $this->Session->read('Config.language'))) {
$this->Session->write('Config.language', $this->params['language']);
$this->Cookie->write('lang', $this->params['language'], false, '20 days');
}
}
}
$config['Settings'] = Configure::read('Settings');
define('SITE_URL', $config['Settings']['SITE_URL']);
define('SITE_NAME', $config['Settings']['SITE_TITLE']);
define('FB_ID', $config['Settings']['FB_ID']);
define('FB_SECRET', $config['Settings']['FB_SECRET']);
define('GOOGLE_ID', $config['Settings']['GOOGLE_ID']);
define('GOOGLE_SECRET', $config['Settings']['GOOGLE_SECRET']);
define('TWITTER_ID', $config['Settings']['TWITTER_ID']);
define('TWITTER_SECRET', $config['Settings']['TWITTER_SECRET']);
define('GMAIL_CLIENT_SECRET', $config['Settings']
['GMAIL_CLIENT_SECRET']);
define('GMAIL_CLIENT_ID', $config['Settings']['GMAIL_CLIENT_ID']);
?>
The first error pointed to this line:
$this->Auth->allow(, , 'login', 'signup', 'emailverification',
so I removed the , , and hence it became:
$this->Auth->allow('login', 'signup', 'emailverification',
The second error pointed to this line $user = ();
So I changed it to $user = $this->Auth->user();
But this change from $user = (); to $user = $this->Auth->user(); throws a fatal error:
Fatal error: Cannot call constructor in /lib/Cake/Controller/CakeErrorController.php on line 46
Below is the content of CakeErrorController.php. I'm told that CakeErrorController.php is a core file so I shouldn't really need to change it?
<?php
/**
* Error Handling Controller
*
* Controller used by ErrorHandler to render error views.
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc.
(http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the
LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* #copyright Copyright (c) Cake Software Foundation, Inc.
(http://cakefoundation.org)
* #link http://cakephp.org CakePHP(tm) Project
* #package Cake.Controller
* #since CakePHP(tm) v 2.0
* #license http://www.opensource.org/licenses/mit-license.php MIT
License
*/
App::uses('AppController', 'Controller');
/**
* Error Handling Controller
*
* Controller used by ErrorHandler to render error views.
*
* #package Cake.Controller
*/
class CakeErrorController extends AppController {
/**
* Uses Property
*
* #var array
*/
public $uses = array();
/**
* Constructor
*
* #param CakeRequest $request
* #param CakeResponse $response
*/
public function __construct($request = null, $response = null) {
parent::__construct($request, $response);
$this->constructClasses();
if (count(Router::extensions()) &&
!$this->Components->attached('RequestHandler')
) {
$this->RequestHandler = $this->Components-
>load('RequestHandler');
}
if ($this->Components->enabled('Auth')) {
$this->Components->disable('Auth');
}
if ($this->Components->enabled('Security')) {
$this->Components->disable('Security');
}
$this->_set(array('cacheAction' => false, 'viewPath' => 'Errors'));
}
}
I need help in fixing any issues you notice with the AppController.php file. I'm new at this. Any help will be much appreciated.
Thanks.
First of all, and I don't want to step on anyone's toes, but, that code looks horrible, there's so much wrong with it I don't even know where to start... global usage, accessing superglobals directly, manually starting a session via native calls, code outside of the class definition, public controller methods that aren't actual actions, massive amounts of unrelated code that should be in concrete controllers and/or components, etc... you really need to get that cleaned up.
That being said, your AppController class doesn't extend Controller (which it must do) and has no constructor itself, so there's no constructor to invoke via parent::__construct() in CakeErrorController::__construct(), hence the error.
See also Cookbook > Controllers
I am trying to create a login/registration form using FOSUserBundle. After logging in the user gets a homepage. wherein he has to choose two different events for 2 time slots from two radio button type options and hit submit. Also if a user has registered already and logs in, then he can see his previously selected choices. Also he can change them. When I created the homepage from inside the controller, the code worked fine.
Here is the controller code:
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\events;
//use AppBundle\Entity\eventtype;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class DefaultController extends Controller {
/**
* #Route("/home", name="homepage")
*/
public function indexAction(Request $request) {
$events = new events();
$greet = 'Welcome to the Birthday Party registration!';
$selection1 = '';
$selection2 = '';
$et1 = 0;
$et2 = 0;
//get the events repository
$repository = $this->getDoctrine()->getRepository('AppBundle:events');
//get the user_id of the logged in user
$user = $this->container->get('security.context')->getToken()->getUser();
$events->setUser($user);
$x = $events->getUser()->getID();
//check if the user has already registered or not
$y = $repository->findOneBy(array('user' => $x));
//If the user has registered already, set the data value for the form
if($y){
$et1 = $y->getET1();
$et2 = $y->getET2();
}
//create form
$form = $this->createFormBuilder($events)
->add('eT1', ChoiceType::class, array(
'choices' => array(
'Poker' => 1,
'Chess' => 2,
'Cricket' => 3,
'Marbles' => 4,
'Football' => 5,
),
'choices_as_values' => true,
'expanded' => true,
'multiple' => false,
'label' => 'Choose After Breakfast Event',
'data' => $et1
))
->add('eT2', ChoiceType::class, array(
'choices' => array(
'Poker' => 1,
'Chess' => 2,
'Cricket' => 3,
'Marbles' => 4,
'Football' => 5,
),
'choices_as_values' => true,
'expanded' => true,
'multiple' => false,
'label' => 'Choose After Snacks Event',
'data' => $et2
))
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
//retrieve the choices array for eT1 and eT2
$eT1Choices = $form->get('eT1')->getConfig()->getOption('choices');
$eT2Choices = $form->get('eT2')->getConfig()->getOption('choices');
//intialize the eventname variables
$eT1Name = '';
$eT2Name = '';
if ($y) {
//If the user has registered already, display his previously selected options
$selection1 = 'Your After Breakfast event:';
$selection2 = 'Your After Snacks event:';
//set the eventname based on the value of et1
foreach ($eT1Choices as $key => $value) {
if ($et1 == $value) {
$eT1Name = $key;
}
}
//set the eventname based on the value of et2
foreach ($eT2Choices as $key => $value) {
if ($et2 == $value) {
$eT2Name = $key;
}
}
}
//after submission
if ($request->isMethod('POST')) {
$form->submit($request);
//retrieve maxlimit parameters from parameters.yml
$maxPoker = $this->container->getParameter('pokermaxlimit');
$maxChess = $this->container->getParameter('chessmaxlimit');
$maxCricket = $this->container->getParameter('cricketmaxlimit');
$maxMarbles = $this->container->getParameter('marblesmaxlimit');
$maxFootball = $this->container->getParameter('footballmaxlimit');
//initialize $eventMaxLim
$eventMaxLim = 0;
//retrieve form data
$formData = $form->getData();
$ET1 = $formData->getET1();
$ET2 = $formData->getET2();
$selection1 = 'Your After Breakfast event:';
$selection2 = 'Your After Snacks event:';
//set the eventname based on the value of eT1
foreach ($eT1Choices as $key => $value) {
if ($ET1 == $value) {
$eT1Name = $key;
}
}
//set the eventname based on the value of eT2
foreach ($eT2Choices as $key => $value) {
if ($ET2 == $value) {
$eT2Name = $key;
}
}
//check to see if the user has registered the same event for eT1 and eT2
if ($ET1 == $ET2) {
$this->get('session')->getFlashBag()->set('error', 'You have chosen same events for both time slots! Please choose different ones.');
}
//check to see how many users have registered for the opted event(eT1)
$query1 = $repository->createQueryBuilder('p')
->select('count(p)')
->where('p.eT1 = :eT1')
->setParameter('eT1', $ET1)
->getQuery();
$a = $query1->getSingleScalarResult();
//set the $eventMaxLim based on the chosen event for eT1
if ($ET1 == 1) {
$eventMaxLim = $maxPoker;
} else if ($ET1 == 2) {
$eventMaxLim = $maxChess;
} else if ($ET1 == 3) {
$eventMaxLim = $maxCricket;
} else if ($ET1 == 4) {
$eventMaxLim = $maxMarbles;
} else if ($ET1 == 5) {
$eventMaxLim = $maxFootball;
}
//check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
if ($a >= $eventMaxLim) {
$this->get('session')->getFlashBag()->set('error', 'choose another After Breakfast event, this one is full');
}
//check to see how many users have registered for the opted event(eT2)
$query2 = $repository->createQueryBuilder('p')
->select('count(p)')
->where('p.eT2 = :eT2')
->setParameter('eT2', $ET2)
->getQuery();
$b = $query2->getSingleScalarResult();
//set the $eventMaxLim based on the chosen event for eT2
if ($ET2 == 1) {
$eventMaxLim = $maxPoker;
} else if ($ET2 == 2) {
$eventMaxLim = $maxChess;
} else if ($ET2 == 3) {
$eventMaxLim = $maxCricket;
} else if ($ET2 == 4) {
$eventMaxLim = $maxMarbles;
} else if ($ET2 == 5) {
$eventMaxLim = $maxFootball;
}
//check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
if ($b >= $eventMaxLim) {
$this->get('session')->getFlashBag()->set('error', 'choose another After Snacks event, this one is full');
}
if (($a < $eventMaxLim) && ($b < $eventMaxLim) && ($ET1 != $ET2)) {
if ($form->isValid()) {
//get the entity manager
$em = $this->getDoctrine()->getManager();
// If the user is registering for the first time (execute the Insert query)
if (!$y) {
$em->persist($events);
$em->flush();
//return $this->redirectToRoute('homepage');
}
//If the user has registered already and want change his registered events (execute the Update query)
else {
$y->setET1($ET1);
$y->setET2($ET2);
$em->persist($y);
$em->flush();
//return $this->redirectToRoute('homepage');
}
}
}
}
return $this->render('default/index.html.twig', array(
'form' => $form->createView(),
'greet' => $greet,
'selection1' => $selection1,
'eT1Name' => $eT1Name,
'selection2' => $selection2,
'eT2Name' => $eT2Name,
));
}
}
Below is the events entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
//use Symfony\Component\Validator\Constraints as Assert;
/**
* events
*
* #ORM\Table(name="events")
* #ORM\Entity(repositoryClass="AppBundle\Repository\eventsRepository")
*/
class events {
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var int
*
* #ORM\Column(name="ET1", type="integer")
*/
protected $eT1;
/**
* #var int
*
* #ORM\Column(name="ET2", type="integer")
*/
protected $eT2;
/**
* #ORM\OneToOne(targetEntity="users", inversedBy="event")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set user
*
* #param users $user
* #return events
*/
public function setUser($user) {
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return events
*/
public function getUser() {
return $this->user;
}
/**
* Set eT1
*
* #param integer $eT1
* #return events
*/
public function setET1($eT1) {
$this->eT1 = $eT1;
return $this;
}
/**
* Get eT1
*
* #return integer
*/
public function getET1() {
return $this->eT1;
}
/**
* Set eT2
*
* #param integer $eT2
* #return events
*/
public function setET2($eT2) {
$this->eT2 = $eT2;
return $this;
}
/**
* Get eT2
*
* #return integer
*/
public function getET2() {
return $this->eT2;
}
}
But when I shifted the code for Form creation in the eventsType.php, The following error has been showing up - A form can only be submitted once 500 Internal Server Error - AlreadySubmittedException
Here is the new controller code:
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\events;
use AppBundle\Form\eventsType;
use AppBundle\Entity\users;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class DefaultController extends Controller {
/**
* #Route("/home", name="homepage")
*/
public function indexAction(Request $request) {
$greet = 'Welcome to the Birthday Party registration!';
$selection1 = '';
$selection2 = '';
//get the events repository
$repository = $this->getDoctrine()->getRepository('AppBundle:events');
//get the user_id of the logged in user
$user = $this->container->get('security.context')->getToken()->getUser()->getID();
//check if the user has already registered or not
$regEvents = $repository->findOneBy(array('user' => $user));
$events = new events();
//create form
$form = $this->createForm(new \AppBundle\Form\eventsType($regEvents), $events);
$form->handleRequest($request);
//retrieve the choices array for eT1 and eT2
$eT1Choices = $form->get('eT1')->getConfig()->getOption('choices');
$eT2Choices = $form->get('eT2')->getConfig()->getOption('choices');
//intialize the eventname variables
$eT1Name = '';
$eT2Name = '';
if ($regEvents) {
$et1 = $regEvents->getET1();
$et2 = $regEvents->getET2();
//If the user has registered already, display his previously selected options
$selection1 = 'Your After Breakfast event:';
$selection2 = 'Your After Snacks event:';
//set the eventname based on the value of et1
foreach ($eT1Choices as $key => $value) {
if ($et1 == $value) {
$eT1Name = $key;
}
}
//set the eventname based on the value of et2
foreach ($eT2Choices as $key => $value) {
if ($et2 == $value) {
$eT2Name = $key;
}
}
}
//after submission
if ($request->isMethod('POST')) {
$form->submit($request);
//First check the value entered by the user
if ($events->getET1() == null || $events->getET2() == null) {
//User did not choose both the events
$this->container->get('session')->getFlashBag()->add('error', 'Oh oh! It is mandatory to choose an option for all the events');
//return array('form' => $form->createView());
}
//retrieve maxlimit parameters from parameters.yml
$maxPoker = $this->container->getParameter('pokermaxlimit');
$maxChess = $this->container->getParameter('chessmaxlimit');
$maxCricket = $this->container->getParameter('cricketmaxlimit');
$maxMarbles = $this->container->getParameter('marblesmaxlimit');
$maxFootball = $this->container->getParameter('footballmaxlimit');
//initialize $eventMaxLim
$eventMaxLim1 = 0;
$eventMaxLim2 = 0;
//retrieve form data
$formData = $form->getData();
$ET1 = $formData->getET1();
$ET2 = $formData->getET2();
$selection1 = 'Your After Breakfast event:';
$selection2 = 'Your After Snacks event:';
//set the eventname based on the value of eT1
foreach ($eT1Choices as $key => $value) {
if ($ET1 == $value) {
$eT1Name = $key;
}
}
//set the eventname based on the value of eT2
foreach ($eT2Choices as $key => $value) {
if ($ET2 == $value) {
$eT2Name = $key;
}
}
//check to see if the user has registered the same event for eT1 and eT2
if ($ET1 == $ET2) {
$this->get('session')->getFlashBag()->set('error', 'You have chosen same events for both time slots! Please choose different ones.');
}
//check to see how many users have registered for the opted event(eT1)
$query1 = $repository->createQueryBuilder('p')
->select('count(p)')
->where('p.eT1 = :eT1')
->setParameter('eT1', $ET1)
->getQuery();
$a = $query1->getSingleScalarResult();
//set the $eventMaxLim based on the chosen event for eT1
if ($ET1 == 1) {
$eventMaxLim1 = $maxPoker;
} else if ($ET1 == 2) {
$eventMaxLim1 = $maxChess;
} else if ($ET1 == 3) {
$eventMaxLim1 = $maxCricket;
} else if ($ET1 == 4) {
$eventMaxLim1 = $maxMarbles;
} else if ($ET1 == 5) {
$eventMaxLim1 = $maxFootball;
}
// var_dump($eventMaxLim1);
// exit;
//check to see if the after breakfast event (eT1) is full (ie.has reached the maxlimit)
if ($a >= $eventMaxLim1) {
$this->get('session')->getFlashBag()->set('error', 'choose another After Breakfast event, this one is full');
}
//check to see how many users have registered for the opted event(eT2)
$query2 = $repository->createQueryBuilder('p')
->select('count(p)')
->where('p.eT2 = :eT2')
->setParameter('eT2', $ET2)
->getQuery();
$b = $query2->getSingleScalarResult();
//set the $eventMaxLim based on the chosen event for eT2
if ($ET2 == 1) {
$eventMaxLim2 = $maxPoker;
} else if ($ET2 == 2) {
$eventMaxLim2 = $maxChess;
} else if ($ET2 == 3) {
$eventMaxLim2 = $maxCricket;
} else if ($ET2 == 4) {
$eventMaxLim2 = $maxMarbles;
} else if ($ET2 == 5) {
$eventMaxLim2 = $maxFootball;
}
//check to see if the after snacks event (eT2) is full (ie.has reached the maxlimit)
if ($b >= $eventMaxLim2) {
$this->get('session')->getFlashBag()->set('error', 'choose another After Snacks event, this one is full');
}
if (($a < $eventMaxLim1) && ($b < $eventMaxLim2) && ($ET1 != $ET2) && ($events->getET1() == null ||
$events->getET2() == null)) {
if ($form->isValid()) {
//get the entity manager
$em = $this->getDoctrine()->getManager();
// If the user is registering for the first time (execute the Insert query)
if (!$regEvents) {
$events->setUser($user);
$events->setET1($ET1);
$events->setET2($ET2);
$em->persist($events);
$em->flush();
//return $this->redirectToRoute('homepage');
}
//If the user has registered already and want change his registered events (execute the Update query)
else {
$events->setET1($ET1);
$events->setET2($ET2);
$em->persist($events);
$em->flush();
//return $this->redirectToRoute('homepage');
}
}
}
}
return $this->render('default/index.html.twig', array(
'form' => $form->createView(),
'greet' => $greet,
'selection1' => $selection1,
'eT1Name' => $eT1Name,
'selection2' => $selection2,
'eT2Name' => $eT2Name,
));
}
}
Below is the eventsType.php:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class eventsType extends AbstractType {
protected $events;
public function __construct($events) {
$this->events = $events;
}
public function buildForm(FormBuilderInterface $builder, array $options) {
if (!empty($this->events)){
if($this->events->getET1() == null){
$et1 = '';
}
else {
$et1 = $this->events->getET1();
}
if($this->events->getET2() == null){
$et2 = '';
}
else {
$et2 = $this->events->getET2();
}
}
else {
$et1 = '';
$et2 = '';
}
$builder->add('eT1', ChoiceType::class, array(
'choices' => array(
'Poker' => 1,
'Chess' => 2,
'Cricket' => 3,
'Marbles' => 4,
'Football' => 5,
),
'choices_as_values' => true,
'expanded' => true,
'multiple' => false,
'label' => 'Choose After Breakfast Event',
'data' => $et1,
// 'mapped' => $map1,
))
->add('eT2', ChoiceType::class, array(
'choices' => array(
'Poker' => 1,
'Chess' => 2,
'Cricket' => 3,
'Marbles' => 4,
'Football' => 5,
),
'choices_as_values' => true,
'expanded' => true,
'multiple' => false,
'label' => 'Choose After Snacks Event',
'data' => $et2,
// 'mapped' => $map2,
))
->add('save', SubmitType::class, array('label' => 'Submit'));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\events',
));
}
}
remove $form->submit($request); from your code and that should stop this error message.
$form->submit($request); (now deprecated) is used to submit the form from your controller, in your case you're using
$form->handleRequest($request); AND $form->submit($request); so as soon as the user presses the submit button submit() is called which again attempts to submit the form and hence the error message "A form can only be submitted once" link to docs
side note:
if ($events->getET1() == null || $events->getET2() == null) {
//User did not choose both the events
$this->container->get('session')->getFlashBag()->add('error', 'msg');
//return array('form' => $form->createView());
}
this if condition can and should be replaced by asserts docs and while flash messages are awesome and very useful this is not the place to use it, you may have misunderstood the usage of it, its used to display success and failure messages after form submission, NOT for validation messages, we have assert messages for that
and also read about MVC patterns and 'separation of concerns', divide your code into parts, one with code that displays content to the user, one that interacts with your database, one that does all the logical processing, the controller is definitely NOT the place to do any of this. the controller must be small most of the time and must make use of the built in functionalities of the framework.
i would suggest to take a break from writing codes and start reading about software architecture, and design patterns, with the current way i dont see much space for progress
-dheeraj
I have to work with the techcrunch wp-async-task to run a synchronization task in background in my wordpress plugin.
So to test, at the bottom of the main file I have :
//top of the php file
require_once(dirname(__FILE__) . '/lib/WP_Async_Task.php');
require_once(dirname(__FILE__) . '/class/my_api_status.class.php');
define('API_URL', '...');
/* ... */
// At the bottom of the file
function my_api_status($api_url)
{
sleep(5);
$r = wp_safe_remote_get($api_url);
if (!is_wp_error($r)) {
$body = json_decode(wp_remote_retrieve_body($r));
if (isset($body->success)) {
return;
}
}
}
add_action('wp_async_api_status', 'my_api_status');
function my_init_api_status()
{
new ApiStatusTask();
do_action('api_status', constant('API_URL'));
}
add_action('plugins_loaded', 'my_init_api_status');
And api status task class
class ApiStatusTask extends WP_Async_Task {
protected $action = 'api_status';
/**
* Prepare data for the asynchronous request
* #throws Exception If for any reason the request should not happen
* #param array $data An array of data sent to the hook
* #return array
*/
protected function prepare_data( $data ) {
return array(
'api_url' => $data[0]
);
}
/**
* Run the async task action
*/
protected function run_action() {
if(isset($_POST['api_url'])){
do_action("wp_async_$this->action", $_POST['api_url']);
}
}
}
The function prepare_data is correctly called by launchand after that launch_on_shutdown is also correctly called and finally wp_remote_post is called at the end of launch_on_shutdown with admin-post.php.
But the function run_action is never called ... and so the my_api_status in the main file.
What it possibly go wrong ?
I will put a complete example of a plugin here soon. But for now, I found my problem :
// In the `launch_on_shutdown` method of `WP_Async_Task` class
public function launch_on_shutdown() {
GcLogger::getLogger()->debug('WP_Async_Task::launch_on_shutdown');
if ( ! empty( $this->_body_data ) ) {
$cookies = array();
foreach ( $_COOKIE as $name => $value ) {
$cookies[] = "$name=" . urlencode( is_array( $value ) ? serialize( $value ) : $value );
}
$request_args = array(
'timeout' => 0.01,
'blocking' => false,
'sslverify' => false, //apply_filters( 'https_local_ssl_verify', true ),
'body' => $this->_body_data,
'headers' => array(
'cookie' => implode( '; ', $cookies ),
),
);
$url = admin_url( 'admin-post.php' );
GcLogger::getLogger()->debug('WP_Async_Task::launch_on_shutdown wp_remote_post');
wp_remote_post( $url, $request_args );
}
}
The sslverify option failed in my local environment. I just had to put it on false if we are not in production.
With this option set, the run_action is correctly trigger.