I need to insert a last4Days option in the reports tab.
I've done that by changing the original files but WooCommerce keeps changing to the original after a while.
So I tried to find a filter to do so, but I'm not finding it.
Unfortunately the Woo team did not do the user-friendly thing and include a filter on the report-length arguments. Short of some meta-programming magic (like dynamically over-writing the arguments in the .php file's text before load, very dangerous) the only way I can see is to go up the instantiation ladder to the point where the report is generated, and then have it call a custom class based on the one you are you using. Luckily WooCommerce does provide a filter for the path to the report file, it's in wc-class-admin-reports.php and the hook is called wc_admin_reports_path. If we were extending the coupon usage report, it would look a little something like:
add_filter('wc_admin_reports_path', 'redirect_coupon_report_class_path', 10, 2);
function redirect_coupon_report_class_path($path, $report_name, $class) {
if($report_name == 'coupon-usage') {
$path = 'path/to/my/custom/class.php';
}
return $path;
}
What you'll need to do is copy the class of the report you're trying to alter, and paste it somewhere in your theme or plugin. Then, add a filter calling a function that will check to see if the report being passed in is the one you want to modify, and redirect it to your custom class. Within your custom class, you can do pretty much whatever you want, but as with any override you'll want to see what they change in that file with each update. You can extend the class like so:
class WC_Report_Coupon_Usage_Custom extends WC_Report_Coupon_Usage {
// Call the parent constructor
function __construct() {
parent::__construct();
}
// Add a method that you would have previously overwritten directly in the plugin file
public function output_report() {
$ranges = array(
'year' => __( 'Year', 'woocommerce' ),
'last_month' => __( 'Last Month', 'woocommerce' ),
'month' => __( 'This Month', 'woocommerce' ),
'7day' => __( 'Last 7 Days', 'woocommerce' ),
'4day' => __( 'Last 4 Days', 'woocommerce' )
);
$this->chart_colours = array(
'discount_amount' => '#3498db',
'coupon_count' => '#d4d9dc',
);
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : '7day';
if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) {
$current_range = '7day';
}
$this->calculate_current_range( $current_range );
include( WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php');
}
}
Related
Currently I am using BP Avatar to create user profile picture in the website.
Now, I want to use the upload and crop + preview function of BP Avatar for another page and another image purpose with custom settings also.
I have tried to copy and edit the code in the new page but it can't work, even the preview.
Hope someone can help.
Thankyou.
Here is the code. I detect the problems start when bbp not detect the user because in the bbp core they get the user id from url, and in my case that dont work. I number the need pieces of code to accomplish. In my case i insert the view inside an endpoint to my-account from woocommerce.
override the function where scripts get the data.
include all the necessary scripts.
insert into my content function.
I use this filter to bp_attachment_avatar_script_data
/**
* Override the avatar script data
*
* #param $script_data
* #param $object
*
* #return int
*/
public function noys_avatar_script_data( $script_data, $object ) {
$user_id = get_current_user_id();
if ( ! empty( $user_id ) ) {
// Should we load the the Webcam Avatar javascript file.
if ( bp_avatar_use_webcam() ) {
$script_data['extra_js'] = array_merge( $script_data['extra_js'], array( 'bp-webcam' ) );
}
$script_data['bp_params'] = array(
'object' => 'user',
'item_id' => $user_id,
'has_avatar' => bp_get_user_has_avatar( $user_id ),
'nonces' => array(
'set' => wp_create_nonce( 'bp_avatar_cropstore' ),
'remove' => wp_create_nonce( 'bp_delete_avatar_link' ),
),
);
// Set feedback messages.
$script_data['feedback_messages'] = array(
1 => __( 'There was a problem cropping your profile photo.', 'buddypress' ),
2 => __( 'Your new profile photo was uploaded successfully.', 'buddypress' ),
3 => __( 'There was a problem deleting your profile photo. Please try again.', 'buddypress' ),
4 => __( 'Your profile photo was deleted successfully!', 'buddypress' ),
);
}
return $script_data;
}
And this is my function to include the content to woocommerce endpoint.
/**
* Endpoint HTML content.
*/
public function profile_picture_endpoints_content1() {
$bd = buddypress();
bp_core_register_common_scripts();
wp_enqueue_style( 'thickbox' );
wp_enqueue_script( 'media-upload' );
bp_core_add_jquery_cropper();
bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' );
bp_attachments_get_template_part( 'avatars/index' );
}
That is all i need to resolve this undocumented problem!
Does anyone know how to properly insert new content categories to the DB programatically?
For each post in the categories table, there is also a post saved in the assets table with lft and rgt set.
Is there any native Joomla class I can use for this instead of plain SQL?
Please Please Only use the native classes, which categories will handle for you seamlessly. As soon as you add categories the whole thing will be handled automagically. Just look at any core component to see how.
It is not easy to update the assets table using sql, it is all very specifically managed and part of a complex series of foreign keyed tables.
Extend JTable or JTableContent to handle this.
Here is some code I just whipped together that just uses the JTableCategory class, so it can be used simply on the front or admin side of Joomla
$table = JTable::getInstance('category');
$data = array();
// name the category
$data['title'] = $title;
// set the parent category for the new category
$data['parent_id'] = $parent_id;
// set what extension the category is for
$data['extension'] = $extension;
// Set the category to be published by default
$data['published'] = 1;
// setLocation uses the parent_id and updates the nesting columns correctly
$table->setLocation($data['parent_id'], 'last-child');
// push our data into the table object
$table->bind($data);
// some data checks including setting the alias based on the name
if ($table->check()) {
// and store it!
$table->store();
// Success
} else {
// Error
}
Naturally you would want to get the data pieces set correctly, but these are the core ones to set.
Here is a function I've created just for this purpose, after some digging & experimenting.
It uses core classes, so it needs an access to them (for me it's basically a part of Joomla component).
Mind, it's for Joomla 3, for Joomla 2.5 and before, you need to change JModelLegacy to JModel.
function createCategory( $name, $parent_id, $note )
{
JTable::addIncludePath( JPATH_ADMINISTRATOR . '/components/com_categories/tables' );
$cat_model = JModelLegacy::getInstance( 'Category', 'CategoriesModel' );
$data = array (
'id' => 0,
'parent_id' => $parent_id,
'extension' => 'com_content',
'title' => $name,
'alias' => '',
'note' => $note,
'description' => '',
'published' => '1',
'access' => '1',
'metadesc' => '',
'metakey' => '',
'created_user_id' => '0',
'language' => '*',
'rules' => array(
'core.create' => array(),
'core.delete' => array(),
'core.edit' => array(),
'core.edit.state' => array(),
'core.edit.own' => array(),
),
'params' => array(
'category_layout' => '',
'image' => '',
),
'metadata' => array(
'author' => '',
'robots' => '',
),
);
if( !$cat_model->save( $data ) )
{
return NULL;
}
$categories = JCategories::getInstance( 'Content' );
$subcategory = $categories->get( $cat_model->getState( "category.id" ) );
return $subcategory;
}
You can perhaps use the save() in category.php file.
File location: root\administrator\components\com_categories\models\category.php
It saves the form data supplied to it!
The JOS_assets table is to store the ACL for each asset that is created.
If you do not update this table while programatically creating the category, the default ACL will apply. And when later you open and save the category in the administrative panel, the ACL will be updated as it should have been by core Joomla!.
You can create an SQL query very easily though and update the asset table as well. Its easy to understand once you open the table's content in phpmyadmin.
I use media-categories-2 plugin for sorting my media files, but i no sort my media files in page->insert media modal window and i cant find needed plugin for this. please help me
I've been trying to figure out how to do this as well. I've gotten as far as creating the categories myself using these snippets http://sumtips.com from in functions.php
add_action('init', 'create_media_categories');
function create_media_categories() {
$labels = array(
'name' => 'Media Category'
);
$args = array(
'labels' => $labels,
'public' => true
);
register_taxonomy('imagetype', 'attachment', $args);
}
Afterwards, I figured out how to create a new option in the Insert Media box:
function custom_media_upload_tab_name( $tabs ) {
$newtab = array( 'tab_slug' => 'Your Tab Name' );
return array_merge( $tabs, $newtab );
}
add_filter( 'media_upload_tabs', 'custom_media_upload_tab_name' );
function custom_media_upload_tab_content() {
// I haven't gotten to this part yet
}
add_action( 'media_upload_tab_slug', 'custom_media_upload_tab_content' );
I'll update it when I figure out the next part!
In my Vacation model Vac I have this function
public function getVacCount(){
this function returns how many days there are in one vacation.
and I want to add a custom column to the cgridview like this:
<?php
$this->widget('zii.widgets.grid.CGridView', array(
...
array(
'name' => 'count',
'value' => '$data->getVacPeriod()'
),
...
),
));
?>
it works fine.
but I don't know how can I sort upon this custom attribute.
I tried to use CSort but it does not work. any idea?
To use CSort for sorting, you'll need to convert your vacation function into a SQL query and then stash the results in a public variable in your model.
CSort only works with SQL statements/functions, as underneath it's using ORDER BY to do all the sorting.
More info (and demo code) available here
Here's a sample of how I'm doing it on a site of mine:
$criteria->select = array(
"*",
new CDbExpression("IF(survey.RequestDate, survey.RequestDate, SurveyCompleteDate) AS SurveyDate")
);
This then allows me to do this type of filter:
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'sort'=>array(
'attributes'=>array(
'SurveyDate' => array(
'asc' => 'SurveyDate',
'desc' => 'SurveyDate DESC',
),
'*',
),
),
);
Note: you'll also need a public variable defined in your model to hold the results of the CDbExpression that you're doing. Mine is called SurveyDate.
I have a number of functions in my controller logic and for every one I have some logic that pulls data for a "featured" set of units. These units are on several pages. How do I go about making this one piece of logic available to all 4 of the views that need it?
For reference, here is part of my controller logic:
public function index() {
$this->set('title', 'All accommodations available in and near Gulf Shores, AL');
$this->Unit->Behaviors->attach('Containable');
$this->Unit->contain(
array(
'User'=>array(
'id'),
'Location',
'Complex'=>array('location_id'),
'Image'=>array(
'logo','img1'
)
)
);
$c=$this->Unit->find('all',
array(
'limit'=>3,
'conditions'=>array(
'active'=>1,
'featured'=>1
)
)
);
$this->set('featured', $c);
$this->paginate['Unit']=array(
'limit'=>9,
'order' => 'RAND()',
'contain'=>array(
'User'=>array('email'),
'Complex'=>array('location_id','complex_website'),
'Location',
'Image'
),
'conditions'=>array(
'Unit.active'=>1)
);
$data = $this->paginate('Unit');
$this->set('allaccommodations', $data);
}
public function houses() {
$this->set('title', 'Home rentals available in Gulf Shores');
$this->Unit->Behaviors->attach('Containable');
$this->Unit->contain(
array(
'User'=>array(
'id'),
'Location',
'Complex'=>array('location_id'),
'Image'=>array(
'logo','img1'
)
)
);
$c=$this->Unit->find('all',
array(
'limit'=>3,
'conditions'=>array(
'active'=>1,
'featured'=>1
)
)
);
$this->set('featured', $c);
$this->paginate['Unit']=array(
'limit'=>9,
'order' => 'RAND()',
'contain'=>array(
'User'=>array('email'),
'Location',
'Image'
),
'conditions'=>array(
'Unit.type'=>array('house', 'rentalco'),
'Unit.active'=>1)
);
$data = $this->paginate('Unit');
$this->set('allhouses', $data);
}
...
I have two other functions that set a 'featured' variable that is available to the view. I'm sure there is a much better/more efficient way to do this?
Yes, the idea is to have all the data interaction in your model and have your controller clear and easy to follow. Fat models, skinny controllers. There are custom finds you can use: http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#creating-custom-find-types
but I prefer to just make a model function because they're easier to work with in the IDE with code completion and documentation. So for the featured find you keep using you could do something in your Unit model like:
public function getFeatured($limit) {
$results = $this->find('all', array(
'limit' => $limit,
'conditions' => array(
'active' => 1,
'featured' => 1
)
)
);
return $results;
}
Then in the UnitController:
$this->set('featured', $this->Unit->getFeatured(3));