Woocommerce custom billing field (also saved, displayed in back-end and on email) - hook-woocommerce

i'm looking for the perfect all in solution. I want to add a custom billing fiels to Woocommerce based on the user ID. Also i want this field to be displayed in the back-end, saved and on the front end on the users profile, and in the mails.
Till now with the code below it only shows the field on the fornt-end
/* Debiteutnummer front-end*/
add_filter('woocommerce_billing_fields', 'custom_woocommerce_billing_fields');
function custom_woocommerce_billing_fields($fields) {
$fields['debiteurnummer'] = array(
'label' => __('debiteurnummer'), // Add custom field label
'placeholder' => _x('Debiteurnummer', 'placeholder', 'woocommerce'), // Add custom field placeholder
'required' => true, // if field is required or not
'clear' => false, // add clear or not
'type' => 'text', // add field type
'class' => array('my-css'), // add class name
'priority' => '150'
);
return $fields;
}
/* Debiteutnummer back-end*/
add_action( 'woocommerce_checkout_update_order_meta', 'custom_save_new_checkout_field' );
function custom_save_new_checkout_field( $order_id ) {
if ( $_POST['debiteurnummer'] ) update_post_meta( $order_id, '_debiteurnummer', esc_attr( $_POST['debiteurnummer'] ) );
}
/* Debiteutnummer on order*/
add_action( 'woocommerce_admin_order_data_after_billing_address', 'custom_show_new_checkout_field_order', 10, 1 );
function custom_show_new_checkout_field_order( $order ) {
$order_id = $order->get_id();
if ( get_post_meta( $order_id, '_debiteurnummer', true ) ) echo '<p><strong>Debiteurnummer:</strong> ' . get_post_meta( $order_id, '_debiteurnummer', true ) . '</p>';
}
/* Debiteutnummer on email*/
add_action( 'woocommerce_email_after_order_table', 'custom_show_new_checkout_field_emails', 20, 4 );
function custom_show_new_checkout_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
if ( get_post_meta( $order->get_id(), '_debiteurnummer', true ) ) echo '<p><strong>License Number:</strong> ' . get_post_meta( $order->get_id(), '_debiteurnummer', true ) . '</p>';
}
Does anybody had an solution or does somebody see what i'm doing wrong?

Related

How to alter woocommerce widget filter by attribute widget?

I use the default Woocommerce widget "Filter by attribute" and I would like to prepend the name of each attributes.
But I don't find any hook on it
Do you know how to achieve this ?
What about extending its class to override the widget?
in your functions.php, add this class, you can then change the elements or do conditional statements depending on what you need.
/**
* Layered nav widget
*
* #package WooCommerce/Widgets
* #version 2.6.0
*/
/**
* Widget layered nav class.
*/
class The_New_Attribute_Widget extends WC_Widget_Layered_Nav {
/**
* Constructor.
*/
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_layered_nav woocommerce-widget-layered-nav';
$this->widget_description = __( 'Display a list of attributes to filter products in your store.', 'woocommerce' );
$this->widget_id = 'woocommerce_layered_nav';
$this->widget_name = __( 'Filter Products by Attribute', 'woocommerce' );
parent::__construct();
}
/**
* Updates a particular instance of a widget.
*
* #see WP_Widget->update
*
* #param array $new_instance New Instance.
* #param array $old_instance Old Instance.
*
* #return array
*/
public function update( $new_instance, $old_instance ) {
$this->init_settings();
return parent::update( $new_instance, $old_instance );
}
/**
* Outputs the settings update form.
*
* #see WP_Widget->form
*
* #param array $instance Instance.
*/
public function form( $instance ) {
$this->init_settings();
parent::form( $instance );
}
/**
* Init settings after post types are registered.
*/
public function init_settings() {
$attribute_array = array();
$std_attribute = '';
$attribute_taxonomies = wc_get_attribute_taxonomies();
if ( ! empty( $attribute_taxonomies ) ) {
foreach ( $attribute_taxonomies as $tax ) {
if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
$attribute_array[ $tax->attribute_name ] = $tax->attribute_name;
}
}
$std_attribute = current( $attribute_array );
}
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'Filter by', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' ),
),
'attribute' => array(
'type' => 'select',
'std' => $std_attribute,
'label' => __( 'Attribute', 'woocommerce' ),
'options' => $attribute_array,
),
'display_type' => array(
'type' => 'select',
'std' => 'list',
'label' => __( 'Display type', 'woocommerce' ),
'options' => array(
'list' => __( 'List', 'woocommerce' ),
'dropdown' => __( 'Dropdown', 'woocommerce' ),
),
),
'query_type' => array(
'type' => 'select',
'std' => 'and',
'label' => __( 'Query type', 'woocommerce' ),
'options' => array(
'and' => __( 'AND', 'woocommerce' ),
'or' => __( 'OR', 'woocommerce' ),
),
),
);
}
/**
* Get this widgets taxonomy.
*
* #param array $instance Array of instance options.
* #return string
*/
protected function get_instance_taxonomy( $instance ) {
if ( isset( $instance['attribute'] ) ) {
return wc_attribute_taxonomy_name( $instance['attribute'] );
}
$attribute_taxonomies = wc_get_attribute_taxonomies();
if ( ! empty( $attribute_taxonomies ) ) {
foreach ( $attribute_taxonomies as $tax ) {
if ( taxonomy_exists( wc_attribute_taxonomy_name( $tax->attribute_name ) ) ) {
return wc_attribute_taxonomy_name( $tax->attribute_name );
}
}
}
return '';
}
/**
* Get this widgets query type.
*
* #param array $instance Array of instance options.
* #return string
*/
protected function get_instance_query_type( $instance ) {
return isset( $instance['query_type'] ) ? $instance['query_type'] : 'and';
}
/**
* Get this widgets display type.
*
* #param array $instance Array of instance options.
* #return string
*/
protected function get_instance_display_type( $instance ) {
return isset( $instance['display_type'] ) ? $instance['display_type'] : 'list';
}
/**
* Output widget.
*
* #see WP_Widget
*
* #param array $args Arguments.
* #param array $instance Instance.
*/
public function widget( $args, $instance ) {
if ( ! is_shop() && ! is_product_taxonomy() ) {
return;
}
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$taxonomy = $this->get_instance_taxonomy( $instance );
$query_type = $this->get_instance_query_type( $instance );
$display_type = $this->get_instance_display_type( $instance );
if ( ! taxonomy_exists( $taxonomy ) ) {
return;
}
$terms = get_terms( $taxonomy, array( 'hide_empty' => '1' ) );
if ( 0 === count( $terms ) ) {
return;
}
ob_start();
$this->widget_start( $args, $instance );
if ( 'dropdown' === $display_type ) {
wp_enqueue_script( 'selectWoo' );
wp_enqueue_style( 'select2' );
$found = $this->layered_nav_dropdown( $terms, $taxonomy, $query_type );
} else {
$found = $this->layered_nav_list( $terms, $taxonomy, $query_type );
}
$this->widget_end( $args );
// Force found when option is selected - do not force found on taxonomy attributes.
if ( ! is_tax() && is_array( $_chosen_attributes ) && array_key_exists( $taxonomy, $_chosen_attributes ) ) {
$found = true;
}
if ( ! $found ) {
ob_end_clean();
} else {
echo ob_get_clean(); // #codingStandardsIgnoreLine
}
}
/**
* Return the currently viewed taxonomy name.
*
* #return string
*/
protected function get_current_taxonomy() {
return is_tax() ? get_queried_object()->taxonomy : '';
}
/**
* Return the currently viewed term ID.
*
* #return int
*/
protected function get_current_term_id() {
return absint( is_tax() ? get_queried_object()->term_id : 0 );
}
/**
* Return the currently viewed term slug.
*
* #return int
*/
protected function get_current_term_slug() {
return absint( is_tax() ? get_queried_object()->slug : 0 );
}
/**
* Show dropdown layered nav.
*
* #param array $terms Terms.
* #param string $taxonomy Taxonomy.
* #param string $query_type Query Type.
* #return bool Will nav display?
*/
protected function layered_nav_dropdown( $terms, $taxonomy, $query_type ) {
global $wp;
$found = false;
if ( $taxonomy !== $this->get_current_taxonomy() ) {
$term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type );
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$taxonomy_filter_name = wc_attribute_taxonomy_slug( $taxonomy );
$taxonomy_label = wc_attribute_label( $taxonomy );
/* translators: %s: taxonomy name */
$any_label = apply_filters( 'woocommerce_layered_nav_any_label', sprintf( __( 'Any %s', 'woocommerce' ), $taxonomy_label ), $taxonomy_label, $taxonomy );
$multiple = 'or' === $query_type;
$current_values = isset( $_chosen_attributes[ $taxonomy ]['terms'] ) ? $_chosen_attributes[ $taxonomy ]['terms'] : array();
if ( '' === get_option( 'permalink_structure' ) ) {
$form_action = remove_query_arg( array( 'page', 'paged' ), add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
} else {
$form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
}
echo '<form method="get" action="' . esc_url( $form_action ) . '" class="woocommerce-widget-layered-nav-dropdown">';
echo '<select class="woocommerce-widget-layered-nav-dropdown dropdown_layered_nav_' . esc_attr( $taxonomy_filter_name ) . '"' . ( $multiple ? 'multiple="multiple"' : '' ) . '>';
echo '<option value="">' . esc_html( $any_label ) . '</option>';
foreach ( $terms as $term ) {
// If on a term page, skip that term in widget list.
if ( $term->term_id === $this->get_current_term_id() ) {
continue;
}
// Get count based on current view.
$option_is_set = in_array( $term->slug, $current_values, true );
$count = isset( $term_counts[ $term->term_id ] ) ? $term_counts[ $term->term_id ] : 0;
// Only show options with count > 0.
if ( 0 < $count ) {
$found = true;
} elseif ( 0 === $count && ! $option_is_set ) {
continue;
}
echo '<option value="' . esc_attr( urldecode( $term->slug ) ) . '" ' . selected( $option_is_set, true, false ) . '>' . esc_html( $term->name ) . '</option>';
}
echo '</select>';
if ( $multiple ) {
echo '<button class="woocommerce-widget-layered-nav-dropdown__submit" type="submit" value="' . esc_attr__( 'Apply', 'woocommerce' ) . '">' . esc_html__( 'Apply', 'woocommerce' ) . '</button>';
}
if ( 'or' === $query_type ) {
echo '<input type="hidden" name="query_type_' . esc_attr( $taxonomy_filter_name ) . '" value="or" />';
}
echo '<input type="hidden" name="filter_' . esc_attr( $taxonomy_filter_name ) . '" value="' . esc_attr( implode( ',', $current_values ) ) . '" />';
echo wc_query_string_form_fields( null, array( 'filter_' . $taxonomy_filter_name, 'query_type_' . $taxonomy_filter_name ), '', true ); // #codingStandardsIgnoreLine
echo '</form>';
wc_enqueue_js(
"
// Update value on change.
jQuery( '.dropdown_layered_nav_" . esc_js( $taxonomy_filter_name ) . "' ).change( function() {
var slug = jQuery( this ).val();
jQuery( ':input[name=\"filter_" . esc_js( $taxonomy_filter_name ) . "\"]' ).val( slug );
// Submit form on change if standard dropdown.
if ( ! jQuery( this ).attr( 'multiple' ) ) {
jQuery( this ).closest( 'form' ).submit();
}
});
// Use Select2 enhancement if possible
if ( jQuery().selectWoo ) {
var wc_layered_nav_select = function() {
jQuery( '.dropdown_layered_nav_" . esc_js( $taxonomy_filter_name ) . "' ).selectWoo( {
placeholder: decodeURIComponent('" . rawurlencode( (string) wp_specialchars_decode( $any_label ) ) . "'),
minimumResultsForSearch: 5,
width: '100%',
allowClear: " . ( $multiple ? 'false' : 'true' ) . ",
language: {
noResults: function() {
return '" . esc_js( _x( 'No matches found', 'enhanced select', 'woocommerce' ) ) . "';
}
}
} );
};
wc_layered_nav_select();
}
"
);
}
return $found;
}
/**
* Count products within certain terms, taking the main WP query into consideration.
*
* This query allows counts to be generated based on the viewed products, not all products.
*
* #param array $term_ids Term IDs.
* #param string $taxonomy Taxonomy.
* #param string $query_type Query Type.
* #return array
*/
protected function get_filtered_term_product_counts( $term_ids, $taxonomy, $query_type ) {
global $wpdb;
$tax_query = WC_Query::get_main_tax_query();
$meta_query = WC_Query::get_main_meta_query();
if ( 'or' === $query_type ) {
foreach ( $tax_query as $key => $query ) {
if ( is_array( $query ) && $taxonomy === $query['taxonomy'] ) {
unset( $tax_query[ $key ] );
}
}
}
$meta_query = new WP_Meta_Query( $meta_query );
$tax_query = new WP_Tax_Query( $tax_query );
$meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
$tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
// Generate query.
$query = array();
$query['select'] = "SELECT COUNT( DISTINCT {$wpdb->posts}.ID ) as term_count, terms.term_id as term_count_id";
$query['from'] = "FROM {$wpdb->posts}";
$query['join'] = "
INNER JOIN {$wpdb->term_relationships} AS term_relationships ON {$wpdb->posts}.ID = term_relationships.object_id
INNER JOIN {$wpdb->term_taxonomy} AS term_taxonomy USING( term_taxonomy_id )
INNER JOIN {$wpdb->terms} AS terms USING( term_id )
" . $tax_query_sql['join'] . $meta_query_sql['join'];
$query['where'] = "
WHERE {$wpdb->posts}.post_type IN ( 'product' )
AND {$wpdb->posts}.post_status = 'publish'"
. $tax_query_sql['where'] . $meta_query_sql['where'] .
'AND terms.term_id IN (' . implode( ',', array_map( 'absint', $term_ids ) ) . ')';
$search = WC_Query::get_main_search_query_sql();
if ( $search ) {
$query['where'] .= ' AND ' . $search;
}
$query['group_by'] = 'GROUP BY terms.term_id';
$query = apply_filters( 'woocommerce_get_filtered_term_product_counts_query', $query );
$query = implode( ' ', $query );
// We have a query - let's see if cached results of this query already exist.
$query_hash = md5( $query );
// Maybe store a transient of the count values.
$cache = apply_filters( 'woocommerce_layered_nav_count_maybe_cache', true );
if ( true === $cache ) {
$cached_counts = (array) get_transient( 'wc_layered_nav_counts_' . sanitize_title( $taxonomy ) );
} else {
$cached_counts = array();
}
if ( ! isset( $cached_counts[ $query_hash ] ) ) {
$results = $wpdb->get_results( $query, ARRAY_A ); // #codingStandardsIgnoreLine
$counts = array_map( 'absint', wp_list_pluck( $results, 'term_count', 'term_count_id' ) );
$cached_counts[ $query_hash ] = $counts;
if ( true === $cache ) {
set_transient( 'wc_layered_nav_counts_' . sanitize_title( $taxonomy ), $cached_counts, DAY_IN_SECONDS );
}
}
return array_map( 'absint', (array) $cached_counts[ $query_hash ] );
}
/**
* Show list based layered nav.
*
* #param array $terms Terms.
* #param string $taxonomy Taxonomy.
* #param string $query_type Query Type.
* #return bool Will nav display?
*/
protected function layered_nav_list( $terms, $taxonomy, $query_type ) {
// List display.
echo '<ul class="woocommerce-widget-layered-nav-list">';
$term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type );
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$found = false;
$base_link = $this->get_current_page_url();
foreach ( $terms as $term ) {
$current_values = isset( $_chosen_attributes[ $taxonomy ]['terms'] ) ? $_chosen_attributes[ $taxonomy ]['terms'] : array();
$option_is_set = in_array( $term->slug, $current_values, true );
$count = isset( $term_counts[ $term->term_id ] ) ? $term_counts[ $term->term_id ] : 0;
// Skip the term for the current archive.
if ( $this->get_current_term_id() === $term->term_id ) {
continue;
}
// Only show options with count > 0.
if ( 0 < $count ) {
$found = true;
} elseif ( 0 === $count && ! $option_is_set ) {
continue;
}
$filter_name = 'filter_' . wc_attribute_taxonomy_slug( $taxonomy );
$current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); // WPCS: input var ok, CSRF ok.
$current_filter = array_map( 'sanitize_title', $current_filter );
if ( ! in_array( $term->slug, $current_filter, true ) ) {
$current_filter[] = $term->slug;
}
$link = remove_query_arg( $filter_name, $base_link );
// Add current filters to URL.
foreach ( $current_filter as $key => $value ) {
// Exclude query arg for current term archive term.
if ( $value === $this->get_current_term_slug() ) {
unset( $current_filter[ $key ] );
}
// Exclude self so filter can be unset on click.
if ( $option_is_set && $value === $term->slug ) {
unset( $current_filter[ $key ] );
}
}
if ( ! empty( $current_filter ) ) {
asort( $current_filter );
$link = add_query_arg( $filter_name, implode( ',', $current_filter ), $link );
// Add Query type Arg to URL.
if ( 'or' === $query_type && ! ( 1 === count( $current_filter ) && $option_is_set ) ) {
$link = add_query_arg( 'query_type_' . wc_attribute_taxonomy_slug( $taxonomy ), 'or', $link );
}
$link = str_replace( '%2C', ',', $link );
}
if ( $count > 0 || $option_is_set ) {
$link = apply_filters( 'woocommerce_layered_nav_link', $link, $term, $taxonomy );
$term_html = '<a rel="nofollow" href="' . esc_url( $link ) . '">' . esc_html( $term->name ) . '</a>';
} else {
$link = false;
$term_html = '<span>' . esc_html( $term->name ) . '</span>';
}
$term_html .= ' ' . apply_filters( 'woocommerce_layered_nav_count', '<span class="count">(' . absint( $count ) . ')</span>', $count, $term );
echo '<li class="woocommerce-widget-layered-nav-list__item wc-layered-nav-term ' . ( $option_is_set ? 'woocommerce-widget-layered-nav-list__item--chosen chosen' : '' ) . '">';
echo apply_filters( 'woocommerce_layered_nav_term_html', $term_html, $term, $link, $count ); // WPCS: XSS ok.
echo '</li>';
}
echo '</ul>';
return $found;
}
}
then in your functions.php again, unregister the default attribute widget and register the new one above:
function your_widget_handler() {
unregister_widget( 'WC_Widget_Layered_Nav' ); //unregister
register_widget( 'The_New_Attribute_Widget' ); //Register the new class
}
add_action( 'widgets_init', 'your_widget_handler' );
I took a look at the source code and it seems that it's only possible if you chose "List" as the "Display type". If so, then there is a filter applied to the displayed elements:
apply_filters( 'woocommerce_layered_nav_term_html', $term_html, $term, $link, $count );
so in order to add custom filter, you can do:
function so_62519320_prepend_name( $term_html, $term, $link, $count ) {
// do stuff
return $some_modified_value;
}
add_filter( 'woocommerce_layered_nav_term_html', 'so_62519320_prepend_name', 10, 4 );
Unfortunately, if you chose "Dropdown" as the "Display type", then there are no filters applied and it seems that you can't modify labels. There's only
esc_html( $term->name )
used to display option labels, so the only way to change this is to change the value in the database.

Yii2 - input search with auto-complete

I am using default Yii2 library for auto-complete. How can I make it, so it is reading values from DB while user is typing?
This is code I have so far, but query is done when the page is created:
echo AutoComplete::widget([
'name' => 'tradeName',
'model' => TradeNames::find()->select('name')->all(),
'options' => [
'class' => 'form-control'
],
'clientOptions' => [
'source' => array_column(TradeNames::find()->select('name')->asArray()->all(), 'name'),
},
],
]);
I followed this advice
jqueryui.com/autocomplete/#multiple and have written next code
<div id="autocomplete" class="ui-widget">
<?= \yii\jui\AutoComplete::widget([
'attribute' => 'attribute',
'name' => 'tradeName',
'clientOptions' => [
'source' => \Yii::$container->get('JsExpression',['function(request, response) {
response( $.ui.autocomplete.filter( window.dataAsArray, extractLast( request.term ) ) );
}']),
'select' => \Yii::$container->get('JsExpression',['function(event, ui) {
var terms = split( this.value );
terms.pop();
terms.push( ui.item.value );
terms.push( "" );
this.value = terms.join( ", " );
return false;
}']),
'focus' => \Yii::$container->get('JsExpression',['function() {
return false;
}']),
]
]) ?>
</div>
<script>
window.dataAsArray = ['item1', 'item2', 'item3'];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(document).ready( function() {
$('#autocomplete').on('keydown', function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
});
});
</script>
maybe it help to someone
try this
use yii\jui\AutoComplete;
use yii\web\JsExpression;
<?php
$data = TradeNames::find()
->select(['name as value', 'name as label','id as id'])
->asArray()
->all();
echo 'Trade Names' .'<br>';
echo AutoComplete::widget([
'name' => 'tradeName',
'id' => 'trade_name',
'clientOptions' => [
'source' => $data,
// 'minLength'=>'3',
'autoFill'=>true,
'select' => new JsExpression("function( event, ui ) {
$('#memberssearch-family_name_id').val(ui.item.id);//#memberssearch-family_name_id is the id of hiddenInput.
}")],
]);
?>
<?= Html::activeHiddenInput($model, 'tradeName')?>

How to add a class to all labels in a ZF2 form

I'm using a jQuery plugin that takes the text from labels associated with form elements and puts them as default text for the fields themselves. (You can find the plugin here.)
Here's the catch: it can only do this if the label has the class "inline". Now, I know I can use the following code to do this:
$this->add(array (
'name' -> 'name',
....
'options' => array (
'label' => 'Name',
'label_attributes' => array (
'class' => 'inline'
)
)
));
This will work fine, and if it has to be done item by item, then so be it. But I was wondering if there's some way I can add the class to ALL labels associated with text and text area form elements without using JavaScript. I'm thinking this would either done by a plugin, or by looping through all the elements in the form, but I don't know how to do either.
You could extend the FormRow view helper.
Here is a little example:
use Zend\Form\View\Helper\AbstractHelper;
use Zend\Form\View\Helper\FormRow;
class CustomFormRow extends FormRow
{
public function render(ElementInterface $element) {
...
$label = $element->getLabel();
if (isset($label) && '' !== $label) {
// Translate the label
if (null !== ($translator = $this->getTranslator())) {
$label = $translator->translate(
$label, $this->getTranslatorTextDomain()
);
}
$label->setAttribute('class', 'inline');
}
...
if ($this->partial) {
$vars = array(
'element' => $element,
'label' => $label,
'labelAttributes' => $this->labelAttributes,
'labelPosition' => $this->labelPosition,
'renderErrors' => $this->renderErrors,
);
return $this->view->render($this->partial, $vars);
}
...
}
You could probably leave the rest as it is and you should be good to go once you add some configuration in your Module.php for your view helper.
public function getViewHelperConfig() {
return array(
'factories' => array(
'CustomFormRow' => function($sm) {
return new \Application\View\Helper\CustomFormRow;
},
)
);
}
In your template files you now have to use your viewHelper instead.
<?php echo $this->CustomFormRow($form->get('yourelement')); ?>

get_permalink to attachment not working

I have following code:
<?php
$args = array(
'post_type' => 'attachment',
'numberposts' => 12,
'post_status' => null
);
$attachments = get_posts( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
echo '<li><a href="'.get_permalink( $attachment->ID ).'">';
echo wp_get_attachment_image( $attachment->ID, array('100', '100') );
echo '</a></li>';
}
}
?>
The point of this script is to show last added 12 photos (thumbs of it). And this works perfect. But I want to add second funcionality - link to the page where it comes from (usually native gallery embed into post/page)
The problem is that in this case the link is corrupted. It always links to the very first post. What I am doing wrong?
Try get_attachment_link($attachment->ID).
Or the_attachment_link($attachment->ID) to directly print the anchor tag with the URL
Here is the final version:)
<?php
$args = array(
'post_type' => 'attachment',
'numberposts' => 12,
'post_status' => null
);
$attachments = get_posts( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
$url = get_permalink( $attachment->ID );
echo '<li><a href="'.strstr($url, '/attachment', true).'">';
echo wp_get_attachment_image( $attachment->ID, array('100', '100') );
echo '</a></li>';
}
}
?>
/attachment is the starting point from which we want to remove everything from the url.

Creating a boolean form widget that accepts null value

My Symfony model has a field which is boolean but also accepts NULL so effectively is a tri-state value.
How can I write a widget for this? Symfony auto-generates a sfWidgetFormCheckbox but that
can not be set to NULL.
I tried a sfWidgetFormChoice with but I had to specify the values as strings to get them work:
$this->setWidget('wt', new sfWidgetFormChoice(array(
'choices' => array(true => 'true', false => 'false', null => 'null')
)));
It works for storing values but whenever I save a "false" value, the select jumps back to 'null'. I tried several combinations of 'false', '0', '' etc. but got nothing to work in all three cases.
Any ideas?
An example right from the docs:
class sfWidgetFormTrilean extends sfWidgetForm
{
public function configure($options = array(), $attributes = array())
{
$this->addOption('choices', array(
0 => 'No',
1 => 'Yes',
'null' => 'Null'
));
}
public function render($name, $value = null, $attributes = array(), $errors = array())
{
$value = $value === null ? 'null' : $value;
$options = array();
foreach ($this->getOption('choices') as $key => $option)
{
$attributes = array('value' => self::escapeOnce($key));
if ($key == $value)
{
$attributes['selected'] = 'selected';
}
$options[] = $this->renderContentTag(
'option',
self::escapeOnce($option),
$attributes
);
}
return $this->renderContentTag(
'select',
"\n".implode("\n", $options)."\n",
array_merge(array('name' => $name), $attributes
));
}
}

Resources