I've been working on a Wordpress theme project over the past few days and I've been stuck on how to get a dynamic options page running properly using OOP (I'm primarily a Theme Developer, not a PHP scripter).
<?php
$footerpage = new optionpage;
$footerpage->title = 'Footer';
$footerpage->titleprint = ' Footer Options';
$footerpage->slug = 'footer';
$footerpage->html = array(
'1' => array(
'type' => 'textarea',
'class' => 'large-text',
'name' => 'html',
'title' => 'HTML',
'description' => 'Type in whatever HTML you\'d like to see in the footer here:',
),
'2' => array(
'type' => 'input',
'class' => 'large-text',
'name' => 'background-color',
'title' => 'Background Color',
'description' => ' Choose a Background Color:'
),
);
class optionpage {
public $title;
public $titleprint;
public $slug;
public $html = array();
......
......
......
public function ab_settings() {
register_setting( $this->slug, 'ab_options');
add_settings_section('ab_section', '', array(&$this, 'ab_do_titleprint'), 'ab_' . $this->slug . '_options', 'ab_options' );
foreach ($this->html as $key => $html) {
add_settings_field( $key, $html['title'], array(&$this, 'ab_do_htmlprint' ), 'ab_' . $this->slug . '_options', 'ab_section');
}
}
public function ab_do_htmlprint() {
$html = $this->html[$key];
?>
<p><?php echo $html['description'] ?></p>
<<?php echo $html['type'] ?>
id="<?php echo $html['id'] ?>"
class="<?php echo $html['class'] ?>"
name="<?php echo $html['name'] ?>">
<?php get_option ($html['name'])?>
</<?php echo $html['type'] ?>>
<?php
}
......
......
?>
In this code example, I'm trying to get the function ab_do_htmlprint to recognize the foreach expressions where it's been called, because the function is going to be called as many times as needed in the foreach loop.
I've tried several things, like appending a variable to the function name, but that would require multiple functions of the same code, just with a different name. I also tried passing various variables by reference and such, however they weren't working either, and I may not have been doing that correctly, if they're even needed.
Anyway to accomplish this efficiently?
If I understand correctly you have an array of values that you want to show in a group on the admin screen as options.
Maybe the shortest example is what i posted here: http://swiftthemes.com/forums/showthread.php?383-SWIFT-on-a-WordPRess-MU-install/page2
p.s. post WordPress questions on http://wordpress.stackexchange.com : more WordPress Experts!
If I understand correctly, you need to pass an argument to ab_do_htmlprint. add_settings_field has parameter for that, do:
add_settings_field( $key, $html['title'], array(&$this, 'ab_do_htmlprint' ), 'ab_' . $this->slug . '_options', 'ab_section', array($key));
then:
public function ab_do_htmlprint($key) {
$html = $this->html[$key];
etc.
I am not familiar with the Wordpress api, so please verify a few assumptions I have. (I know this is not an answer, but I do not want to put as a comment for readability)
1) ab_settings() is called somewhere?
2) Is the section you are having issues with?
foreach ($this->html as $key => $html) {
add_settings_field( $key, $html['title'], array(&$this, 'ab_do_htmlprint' ),
'ab_' . $this->slug . '_options', 'ab_section');
}
3) $key is magically available or do you need to provide it as an argument?
public function ab_do_htmlprint() {
$html = $this->html[$key];`
Also, the format of your ab_do_htmlprint function is very hard to read and could be a source of error. Try using HEREDOC notation or purely PHP strings
ex) Instead of
public function ab_do_htmlprint() {
$html = $this->html[$key];
?>
<p><?php echo $html['description'] ?></p>
<<?php echo $html['type'] ?>
id="<?php echo $html['id'] ?>"
class="<?php echo $html['class'] ?>"
name="<?php echo $html['name'] ?>">
<?php get_option($html['name'])?>
</<?php echo $html['type'] ?>>
<?php
}
as
public function ab_do_htmlprint() {
$html = $this->html[$key];
$output = "<p>{$html['description']}</p>";
$output .= "<{$html['type']} id=\"{$html['id']}\"";
$output .= " class=\"{$html['class']}\"";
$output .= " name=\"{$html['name']}\">";
get_option( $html['name'] );
$output .= "</{$html['type']}>";
echo $output;
}
Related
I have a page where 'Tests' are done on tasks. Currently it will load the tasks and clicking Perform it would run the tests on these tasks. But I need to modify in such way that instead of it selecting all the tasks it should allow me to select the tasks to perform tests on using a checkbox on the side of the tasks.
The code:
<?php
/* #var $this AssetController */
/* #var $form MyActiveForm */
/* #var $model Asset */
?>
<?php
foreach ($model->userCheckSpecifications as $userCheckSpec) {
?>
<h3><?= $userCheckSpec->name ?></h3>
<?php
$serviceTaskSearch = new ServiceTask;
$serviceTaskSearch->service_specification_id = $userCheckSpec->id;
$checkDataProvider = $serviceTaskSearch->search();
$this->widget('zii.widgets.CListView', array(
'dataProvider' => $checkDataProvider,
'itemView' => '_serviceSpecificationTemplate', // refers to the partial view named '_serviceSpecificationTemplate'
'template' => '{items}',
'viewData' => array(
'dataCount' => count($checkDataProvider->data)
),
));
?>
<div class="clear"></div>
<?php
if (!empty($checkDataProvider->data)) {
$dialogScript = '';
$dialogScript .= "openDialog('" . Yii::app()->createUrl('assetService/performUserChecks',
array('assetId' => $model->id,
'serviceSpecificationId' => $userCheckSpec->id,
'parentGridName' => 'user-check-grid')) . "','Perform " . $userCheckSpec->name . " Checks','Perform" . str_replace(" ", "", $userCheckSpec->name) . "ChecksDialog');";
echo CHtml::button("Perform Checks", array('class' => 'btn btn-primary', "onclick" => $dialogScript));
?>
<div class="clear"></div>
<?php
}
}
?>
Code in Asset.php
this code for userCheckSpecifications:
public function getUserCheckSpecifications()
{
$criteria = new CDbCriteria;
$criteria->compare('t.user_check', 1);
if ($this->use_model_service_specification) {
$criteria->compare('t.manufacturer_model_id', $this->manufacturer_model_id);
} else {
if (!empty($this->manufacturerModel)) {
$criteria->compare('t.asset_type_id', $this->manufacturerModel->asset_type_id);
} else {
return array();
}
}
$criteria->addCondition('t.organisation_id = :assetOrganisationId OR t.organisation_id = :userOrganisationId');
$criteria->params[':assetOrganisationId'] = $this->organisation->id;
$criteria->params[':userOrganisationId'] = Yii::app()->user->userModel->organisation_id;
return ServiceSpecification::model()->findAll($criteria);
}
Any and all help gratefully appreciated.
I'm trying to create a simple shortcode for wordpress that has the following variables:
- username
- no_of_tweets
So a user could write [twitter_feed username="USERNAME" no_of_tweets="5"]
and it displays a list of 5 of their latest tweets. I have been using a plugin called Twitter Feed for developers - it does all the oAuth stuff and the idea is that you just write the code to output some front end html.
I have it working except for one annoying glitch - I can't get the no_of tweets to work.
This code works, but doesn't allow for users to specify the no_of_tweets variable:
extract( shortcode_atts(
array(
'username' => 'skizzar_sites',
'no_of_tweets' => '3',
), $atts )
);
// Code
$tweets = getTweets(3, $username);
...
If I were tochange the code to the following (i.e. change the "3" in the $tweets variable, the code stops working:
extract( shortcode_atts(
array(
'username' => 'skizzar_sites',
'no_of_tweets' => '5',
), $atts )
);
// Code
$tweets = getTweets($no_of_tweets, $username);
Is there any reason why this might not be working correctly?
See full code below:
<?php
// Add Shortcode
function skizzar_twitter_feed( $atts ) {
// Attributes
extract( shortcode_atts(
array(
'username' => 'skizzar_sites',
'no_of_tweets' => '5',
), $atts )
);
// Code
$tweets = getTweets($no_of_tweets, $username);//change number up to 20 for number of tweets
if(is_array($tweets)){
// to use with intents
echo '<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script>';
foreach($tweets as $tweet){
if($tweet['text']){
$the_tweet = $tweet['text'];
if(is_array($tweet['entities']['user_mentions'])){
foreach($tweet['entities']['user_mentions'] as $key => $user_mention){
$the_tweet = preg_replace(
'/#'.$user_mention['screen_name'].'/i',
'#'.$user_mention['screen_name'].'',
$the_tweet);
}
}
if(is_array($tweet['entities']['hashtags'])){
foreach($tweet['entities']['hashtags'] as $key => $hashtag){
$the_tweet = preg_replace(
'/#'.$hashtag['text'].'/i',
'#'.$hashtag['text'].'',
$the_tweet);
}
}
if(is_array($tweet['entities']['urls'])){
foreach($tweet['entities']['urls'] as $key => $link){
$the_tweet = preg_replace(
'`'.$link['url'].'`',
''.$link['url'].'',
$the_tweet);
}
}
echo $the_tweet;
echo '
<ul class="twitter_intents">
<li><a class="reply" href="https://twitter.com/intent/tweet?in_reply_to='.$tweet['id_str'].'"><i class="fa fa-reply"></i></a></li>
<li><a class="retweet" href="https://twitter.com/intent/retweet?tweet_id='.$tweet['id_str'].'"><i class="fa fa-retweet"></i></a></li>
<li><a class="favorite" href="https://twitter.com/intent/favorite?tweet_id='.$tweet['id_str'].'"><i class="fa fa-star"></i></a></li>
</ul>';
echo '
<p class="timestamp">
<a href="https://twitter.com/'.$username.'/status/'.$tweet['id_str'].'" target="_blank">
'.date('h:i A M d',strtotime($tweet['created_at']. '- 8 hours')).'
</a>
</p>';// -8 GMT for Pacific Standard Time
} else {
echo '
<br /><br />
Click here to read '.$username.'\'S Twitter feed';
}
}
}
}
add_shortcode( 'twitter_feed', 'skizzar_twitter_feed' );
Here is the getTweets function code:
/* implement getTweets */
function getTweets($username = false, $count = 20, $options = false) {
$config['key'] = get_option('tdf_consumer_key');
$config['secret'] = get_option('tdf_consumer_secret');
$config['token'] = get_option('tdf_access_token');
$config['token_secret'] = get_option('tdf_access_token_secret');
$config['screenname'] = get_option('tdf_user_timeline');
$config['cache_expire'] = intval(get_option('tdf_cache_expire'));
if ($config['cache_expire'] < 1) $config['cache_expire'] = 3600;
$config['directory'] = plugin_dir_path(__FILE__);
$obj = new StormTwitter($config);
$res = $obj->getTweets($username, $count, $options);
update_option('tdf_last_error',$obj->st_last_error);
return $res;
}
I need to show in the category page of opencart
Starting at € xx.xx if this product have options.
Something like this:
if (have options) {
print starting at $price
} else {
print $price }
category.tpl contains:
<p class="price">
<?php if (!$product['special']) { ?>
<?php echo $product['price']; ?>
<?php } else { ?>
<span class="price-new"><?php echo $product['special']; ?></span> <span class="price-old"><?php echo $product['price']; ?></span>
<?php } ?>
<?php if ($product['tax']) { ?>
<span class="price-tax"><?php echo $text_tax; ?> <?php echo $product['tax']; ?></span>
<?php } ?>
I need to insert another controller that, if we have options show "starting at €..." instead the price.
Thank you all,
Davide
I needed something similar for a client in Opencart (v1.5.5.1). The following code checks to see if there is an option with a price increase and if so puts 'From price' on the category page:
Add the following function to \catalog\model\catalog\product.php
public function hasOptionPriceIncrease($product_id) {
$option_data = $this->getProductOptions($product_id);
if (is_array($option_data)) {
foreach ($option_data as $option) {
if (is_array($option['option_value'])) {
foreach ($option['option_value'] as $value) {
if ($value['price'] > 1) {
return true;
}
}
}
}
}
return false;
}
in opencart > 2.0 use product_option_value instead of option_value:
public function hasOptionPriceIncrease($product_id) {
$option_data = $this->getProductOptions($product_id);
if (is_array($product_option_value)) {
foreach ($product_option_value as $option) {
if (is_array($option['product_option_value'])) {
foreach ($option['product_option_value'] as $value) {
if ($value['price'] > 1) {
return true;
}
}
}
}
}
return false;
}
Then add the following line to the $this->data['products'][] array in the category controller: \controller\product\category.php
'has_option_price_increase' =>$this->model_catalog_product->hasOptionPriceIncrease($result['product_id'])
This is at around line 250 on mine but yours maybe a bit different it goes in here:
$this->data['products'][] = array(
'product_id' => $result['product_id'],
'thumb' => $image,
'name' => $result['name'],
'description' => utf8_substr(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')), 0, 100) . '..',
'price' => $price,
'special' => $special,
'tax' => $tax,
'rating' => $result['rating'],
'reviews' => sprintf($this->language->get('text_reviews'), (int)$result['reviews']),
'href' => $this->url->link('product/product', 'path=' . $this->request->get['path'] . '&product_id=' . $result['product_id'] . $url),
'has_option_price_increase' =>$this->model_catalog_product->hasOptionPriceIncrease($result['product_id'])
);
Don't forget to add the comma at the end of the preceding line.
Then you can add something similar to the following in the view: \catalog\view\theme\duvalay\template\product\category.tpl
<p class="price">
<?php if ($product['has_option_price_increase']) { echo 'From'; } ?>
The solution posted by jx12345 is very useful, however, I spent the better part of the afternoon trying to figure out why it wasn't working on OC v2.0.3.1 and figured out that the solution was simply a matter of changing the original array check variable. The original variable he has
$option_data
needs to be changed to
$product_option_value
So the final code to add to the model file looks something like this:
public function hasOptionPriceIncrease($product_id) {
$product_option_value = $this->getProductOptions($product_id);
if (is_array($product_option_value)) {
foreach ($product_option_value as $option) {
if (is_array($option['product_option_value'])) {
foreach ($option['product_option_value'] as $value) {
if ($value['price'] > 1) {
return true;
}
}
}
}
}
return false;
}
At least this is what was necessary to get the code working for me.
Thanks for the contribution jx12345!
We have two models which are related by a has and belongs to many (HABTM) relationship: Jobs, Tests. We are able to add/edit the relationships successfully (we know because they show up in the join table), but we can't get the existing values to appear in the view. The select/checkboxes (we've tried both) are always empty.
Here are the model relationships:
//Job.php
public $hasAndBelongsToMany = array (
'Test' => array (
'classname' => 'Test',
'foreignKey'=>'job_id',
'joinTable' => 'jobs_tests',
'associatedForeignKey' => 'test_id'
)
);
//Test.php
public $hasAndBelongsToMany = array(
'Job' => array(
'className'=> 'Job',
'joinTable'=>'jobs_tests',
'foreignKey' => 'test_id',
'associatedForeignKey'=> 'job_id'
)
);
Here is the /view/Jobs/edit.ctp
echo $this->Form->select('Test', $test_options, array('class'=>'form-control', 'multiple'=>'checkbox'));
//This is always empty (nothing selected/checked).
What are we doing wrong?
Update:
Here is the JobsController action:
public function admin_edit( $id=NULL ) {
$this->layout = 'admin';
if (!$id)
$this->redirect( array('controller'=>'jobs', 'action'=>'index'));
$this->loadModel('Company');
$companies = $this->Company->find('all');
$company_options = array();
foreach ($companies as $company) {
$company_options[ $company['Company']['id'] ] = $company['Company']['name'];
}
$this->set('company_options', $company_options);
$this->loadModel('Test');
$tests = $this->Test->find('all');
$tests_options = array();
foreach ($tests as $test) {
$test_options[ $test['Test']['id'] ] = $test['Test']['name'];
}
$this->set('test_options', $test_options);
$category_options = $this->Job->validCategories;
$this->set('category_options', $category_options);
if ($this->request->isPut() ) {
$data = $this->request->data;
//debug($data);exit;
$save = $this->Job->save( $data );
if ($save) {
$this->Session->setFlash('Job edited');
//$job = $this->Job->findById( $id );
} else {
$this->Session->setFlash('Error editting job');
}
}
$job = $this->Job->findById($id);
$this->request->data = $job;
$this->set('job', $job);
}
Here is the form in the admin_edit.ctp view:
<?php echo $this->Form->create('Job'); ?>
<fieldset>
<?php
echo $this->Form->input('id', array('type'=>'hidden'));
echo $this->Form->input('name', array('class'=>'form-control'));
echo $this->Form->input('email', array('class'=>'form-control'));
echo $this->Form->input('location', array('class'=>'form-control'));
echo '<label>Type</label>';
echo $this->Form->select('type', array('FT'=>'Full Time', 'PT'=>'Part Time', 'IN'=>'Internship'), array('empty'=>false, 'class'=>'form-control'));
echo '<label>Company</label>';
echo $this->Form->select('company_id', $company_options, array('class'=>'form-control'));
echo $this->Form->input('short_description', array('label' => 'Short Description', 'class'=>'form-control'));
echo $this->Form->input('full_description', array('type'=>'textarea', 'label' => 'Full Description', 'class'=>'form-control'));
echo $this->Form->input('is_private', array('label'=>'Is Private?', 'class'=>'form-control') );
echo '<label>Category</label>';
echo $this->Form->select('category', $category_options, array('class'=>'form-control'));
echo '<label>Tests</label>';
//echo $this->Form->select('Test.id', $test_options, array('class'=>'form-control', 'multiple'=>true));
$selected = array();
foreach ($job['Test'] as $test) {
$selected[]=$test['id'];
//$selected[ $test['id'] ] = $test['name'];
}
debug($selected);
echo $this->Form->input('Test', array('type'=>'select', 'options'=>$test_options, 'class'=>'form-control', 'multiple'=>'checkbox', 'selected'=>$selected));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
PHEW! This was a stumper but the solution turned out to be simple... The values in $options['selected'] were strings (of numbers), which was confusing CakePHP. We converted them to ints using intval() and it works perfectly now, using all the original settings...
Here's the revised version of what is in the view (notice the intval()):
$selected = array();
foreach ($job['Test'] as $test) {
$selected[]= intval($test['id']);
}
echo $this->Form->input('Test', array('type'=>'select', 'options'=>$test_options, 'class'=>'form-control', 'multiple'=>'checkbox', 'selected'=>$selected));
Also, as a sidenote, this is evidence that pretty much everything that was challenged in the comments above works completely fine:
$options['selected'] does not need to be key=>value pairs.
The pattern we're using does not overwrite the request->data and passes the data to the form helper just fine.
non-camelCased variable names passed to the view ($some_variable_name) are still picked up correctly by the form helper.
Hopefully this comes in handy to someone else.
What if you pass set the default values using Model::find('list').
//controller
$this->set('test_options', $this->YourModel->find('list'));
//view
echo $this->Form->select('Test', $test_options, array('class'=>'form-control', 'multiple'=>'checkbox'));
How do I assign unique static strings to a variable in a for loop? I'm trying assign a unique description and alt tag to a list of thumbnails. I have managed to get the loop to produce the thumbnails but I cannot work out how to assign unique values to each one based on the condition of the value. This is the for loop:
<?php
for ( $project=1; $project<=40; $project++ ) {
echo "
<a href=\"#\" class=\"thumb\">
<img src=\"images/thumbs/$project.jpg\" width=\"300\" height=\"140\" alt=\"$projectname\" title=\"$projectname\" />
<span class=\"client\">$projectname</span><span class=\"description\">$type</span>
</a>
";
}
?>
I tried this before the for loop but didn't work...
if ( $project = 1 ) {
$projectname = "client1";
$type = "Interactive Brochure Design";
}
else if ( $project = 2 ) {
$projectname = "client2";
$type = "Site Design";
}
if ( $project == 1 ) {
$projectname = "client1";
$type = "Interactive Brochure Design";
}
else if ( $project == 2 ) {
$projectname = "client2";
$type = "Site Design";
}
= sets a variable and doesnt compare. == compares
of course there are probably more elegant ways for your project...
You would usually begin with storing each project in an array, so you can easily loop through them. The values stored in the array could be objects of some "project" class, or an associative array, like this:
$projects = array(
array(
'name' => 'client1',
'type' => 'Interactive Brochure Design',
'filename' => 'client1.jpg',
),
array(
'name' => 'client2',
'type' => 'Site Design',
'filename' => 'client2.jpg',
),
);
foreach($projects as $project)
echo '
<a href="#" class="thumb">
<img src="images/thumbs/'.$project['filename'].'" width="300" height="140" alt="'.$project['name'].'" title="'.$project['name'].'" />
<span class="client">'.$project['name'].'</span><span class="description">'.$project['type'].'</span>
</a>
';
That's what arrays are there for. Something like:
$projects = array(
array('name' => 'client1', 'type' => 'Interactive Brochure Design'),
array('name' => 'client2', 'type' => 'Site Design'),
);
for ($n=0; $n<count($projects); ) {
$projectname = $projects[$n]['name'];
$type = $projects[$n]['type'];
$project = ++$n;
echo "
<a href=\"#\" class=\"thumb\">
<img src=\"images/thumbs/$project.jpg\" width=\"300\" height=\"140\" alt=\"$projectname\" title=\"$projectname\" />
<span class=\"client\">$projectname</span><span class=\"description\">$type</span>
</a>
";
}
Or you could also use foreach:
foreach ($projects as $project) {
echo '<div>name: ' . $project['name'] . '</div>
<div>type: ' . $project['type'] . '</div>';
}
See it on codepad