Last week a released a 2.0 beta version of my Events Manager plugin, which produces a list of events. Among the many bugs floating around, there is one I cannot fix. The bug seems to manifest itself only on a tester's server with PHP 4.4.8; works allright on PHP 5.
When I try to use the H:i php time format, I always get midnight (00:00).
The issue is with the wordpress function mysql2date. This function is a wrapper around the date function.
I isolated the problem and inserted this in the website template:
echo (mysql2date("H:i", "0000-00-00 13:24:00"));
The result was
00:00
At first I thought it was a wordpress bug, but then I rewrote my function to employ date() straightaway. The result was even stranger, instead of midnight I got 11:59.
Quite strangerly, both mysql2date and date seem to work allright on every other part of the plugin. Also, as I said, I cannot reproduce the bug on my server, only 2 users signalled it.
Since I was asked, here's the mysql2date code; it's part of Wordpress:
/**
* Converts MySQL DATETIME field to user specified date format.
*
* If $dateformatstring has 'G' value, then gmmktime() function will be used to
* make the time. If $dateformatstring is set to 'U', then mktime() function
* will be used to make the time.
*
* The $translate will only be used, if it is set to true and it is by default
* and if the $wp_locale object has the month and weekday set.
*
* #since 0.71
*
* #param string $dateformatstring Either 'G', 'U', or php date format.
* #param string $mysqlstring Time from mysql DATETIME field.
* #param bool $translate Optional. Default is true. Will switch format to locale.
* #return string Date formated by $dateformatstring or locale (if available).
*/
function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
global $wp_locale;
$m = $mysqlstring;
if ( empty( $m ) )
return false;
if( 'G' == $dateformatstring ) {
return gmmktime(
(int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ), (int) substr( $m, 17, 2 ),
(int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int) substr( $m, 0, 4 )
);
}
$i = mktime(
(int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ), (int) substr( $m, 17, 2 ),
(int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int) substr( $m, 0, 4 )
);
if( 'U' == $dateformatstring )
return $i;
if ( -1 == $i || false == $i )
$i = 0;
if ( !empty( $wp_locale->month ) && !empty( $wp_locale->weekday ) && $translate ) {
$datemonth = $wp_locale->get_month( date( 'm', $i ) );
$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
$dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
$datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) );
$datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) );
$dateformatstring = ' ' . $dateformatstring;
$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
}
$j = #date( $dateformatstring, $i );
/*
if ( !$j ) // for debug purposes
echo $i." ".$mysqlstring;
*/
return $j;
}
If you're interested, you can download the code of my plugin here, the problem is on line 613 of events-manager.php.
Can this have something to do with PHP or apache settings?
Thanks in advance for any suggestion.
Davide
Not a fix, but an alternative - use UNIX_TIMESTAMP in your mysql statement instead of converting it afterwards.
SELECT UNIX_TIMESTAMP(date_created) AS date
I guess I have solved this issue. The problem was 0000-00-00, apparently not a valid time mysql2date value in some PHP/MySql combos (quite understandably, I am looking at you, month 00...) . I ended up using echo (mysql2date("H:i", "2000-10-10 13:24:00"));
Since I am just interested in the hours and minute a more casual date does the job. Problem solved.
Related
Want to convert the following tstzrange of PostgreSQL to strtotime() in PHP:-
["01/01/2019 00:00:00 MST","05/01/2019 00:00:00 MDT")
tried following things but unable to convert properly.
$arrmixExtractDates = explode( ',', $arrobjLastExtractRange[0]->getExtractRange() );
$strRangeLowerBoundTime = strtotime( str_replace( 'MST', '', ltrim( $arrmixExtractDates[0], '[' ) ) );
$strRangeUpperBoundTime = strtotime( str_replace( 'MDT', '', rtrim( $arrmixExtractDates[1], ')' ) ) );
I am working on my WordPress / Woocommerce website.
How can I add a constant value, which would always be the first value in the drop down list which consists of times (hour:minute). This constant value at the top should say "As soon as possible".
Here is the code which generates the form itself:
public function time_select( $checkout ) {
echo '<div id="local-pickup-time-select"><h2>' . __( 'Delivery Time', $this->plugin_slug ) . '</h2>';
woocommerce_form_field( 'local_pickup_time_select', array(
'type' => 'select',
'class' => array( 'local-pickup-time-select-field form-row-wide' ),
'label' => __( 'Delivery Time', $this->plugin_slug ),
'required' => true,
'options' => self::create_hour_options()
), $checkout->get_value( 'local_pickup_time_select' ));
self::create_hour_options();
echo '</div>';
}
public function pickup_time_select_translatable( $value ) {
$value = preg_replace('/(\d)_(\d)/','$1:$2', $value);
$value = explode('_', $value);
$return = __( $value[0], $this->plugin_slug ). ' ' .$value[1];
return $return;
}
public function create_hour_options() {
// Make sure we have a time zone set
$offset = get_option( 'gmt_offset' );
$timezone_setting = get_option( 'timezone_string' );
if ( $timezone_setting ) {
date_default_timezone_set( get_option( 'timezone_string', 'America/New_York' ) );
}
else {
$timezone = timezone_name_from_abbr( null, $offset * 3600, true );
if( $timezone === false ) $timezone = timezone_name_from_abbr( null, $offset * 3600, false );
date_default_timezone_set( $timezone );
}
// Get days closed textarea from settings, explode into an array
$closing_days_raw = trim( get_option( 'local_pickup_hours_closings' ) );
$closing_days = explode( "\n", $closing_days_raw );
$closing_days = array_filter( $closing_days, 'trim' );
// Get delay, interval, and number of days ahead settings
$delay_minutes = get_option( 'local_pickup_delay_minutes', 60 );
$interval = get_option( 'local_pickup_hours_interval', 30 );
$num_days_allowed = get_option( 'local_pickup_days_ahead', 1 );
// Setup time variables for calculations
$today_name = strtolower( date( 'l' ) );
$today_date = date( 'm/d/Y' );
// Create an empty array for our dates
$pickup_options = array();
//Translateble days
__( 'Monday', $this->plugin_slug );
__( 'Tuesday', $this->plugin_slug );
__( 'Wednesday', $this->plugin_slug );
__( 'Thursday', $this->plugin_slug );
__( 'Friday', $this->plugin_slug );
__( 'Saturday', $this->plugin_slug );
__( 'Sunday', $this->plugin_slug );
// Add empty option
$pickup_options[''] = __( 'Select time', $this->plugin_slug );
// Loop through all days ahead and add the pickup time options to the array
for ( $i = 0; $i < $num_days_allowed; $i++ ) {
// Get the date of current iteration
$current_day_name = date( 'l', strtotime( "+$i days" ) );
$current_day_name_lower = strtolower( $current_day_name );
// Get the day's opening and closing times
$open_time = get_option( 'local_pickup_hours_' . $current_day_name_lower . '_start', '10:00' );
$close_time = get_option( 'local_pickup_hours_' . $current_day_name_lower . '_end', '19:00' );
// Today
$tStart = strtotime( $open_time );
$tEnd = strtotime( $close_time );
$tNow = $tStart;
$current_time = time();
// Date format based on user settings
$date_format = get_option('time_format');
$date_format_key = preg_replace("/[^\w]+/", "_", $date_format);
// If Closed today or today's pickup times are over, don't allow a pickup option
if ( ( in_array( $today_date, $closing_days ) || ( $current_time >= $tEnd ) ) && $num_days_allowed == 1 ) {
// Set drop down text to let user know store is closed
$pickup_options['closed_today'] = __( 'Closed today, please check back tomorrow!', $this->plugin_slug );
// Hide Order Review so user doesn't order anything today
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );
}
else {
// Create array of time options to return to woocommerce_form_field
// Today
if ( $i == 0) {
// Check if it's not too late for pickup
if ( $current_time < $tEnd ) {
// Fix tNow if is pickup possible today
if ( $i == 0 ) {
$todayStart = $tStart;
$delayStart = strtotime("+$delay_minutes minutes", $current_time);
while ( $todayStart <= $delayStart ) {
$todayStart = strtotime("+$interval minutes", $todayStart);
}
$tNow = $todayStart;
}
while ( $tNow <= $tEnd ) {
$day_name = __( 'Today', $this->plugin_slug );
$option_key = $current_day_name . date( $date_format_key, $tNow );
$option_value = $day_name . ' ' . date( $date_format, $tNow );
$pickup_options[$option_key] = $option_value;
$tNow = strtotime( "+$interval minutes", $tNow );
}
}
// Other days
} else {
if ( !empty($open_time) && !empty($close_time )) {
while ( $tNow <= $tEnd ) {
$day_name = __( $current_day_name, $this->plugin_slug );
$option_key = $current_day_name . date( $date_format_key, $tNow );
$option_value = $day_name . ' ' . date( $date_format, $tNow );
$pickup_options[$option_key] = $option_value;
$tNow = strtotime( "+$interval minutes", $tNow );
}
}
}
}
} // end for loop
if ( count($pickup_options) == 1) {
// Set drop down text to let user know store is closed
$pickup_options['closed_today'] = __( 'Closed today, please check back tomorrow!', $this->plugin_slug );
// Hide Order Review so user doesn't order anything today
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );
}
return $pickup_options;
}
The final result would look something like this Drop-down list:
As soon as possible
Tuesday 7:30 pm
Tuesday 8:00 pm
Tuesday 8:30 pm
There is many ways to do it depending if the key value you want for "As soon as possible" choice has to be dynamic. This is done in your first function with array_merge() this way:
public function time_select( $checkout ) {
echo '<div id="local-pickup-time-select"><h2>' . __( 'Delivery Time', $this->plugin_slug ) . '</h2>';
// The default empty value and your translatable sentence to be included
$array_to_insert = array(
'' => __( 'Select your delivery time', $this->plugin_slug ),
'as_soon' => __( 'As soon as possible', $this->plugin_slug )
);
// Getting your calculated hours options array
$options = self::create_hour_options();
// Merging both arrays in one
$options = array_merge( $array_to_insert, $options );
woocommerce_form_field( 'local_pickup_time_select', array(
'type' => 'select',
'class' => array( 'local-pickup-time-select-field form-row-wide' ),
'label' => __( 'Delivery Time', $this->plugin_slug ),
'required' => true,
'options' => $options,
), $checkout->get_value( 'local_pickup_time_select' ));
echo '</div>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works. you will get that:
I have noticed in your code that your //Translateble days (monday to sunday) are not set in individual variables or in an array…
I'd like to list all years from which there are public Wordpress posts, and in a sub-menu below, the months from those years. Example:
2016
August
March
2015
June
May
February
I have a working version of this inside a loop, but it requires me to manually add a new list every year. Is there any way to adjust it, so that it includes the new year automatically?
<h1>2016</h1>
<ul>
<?php
$string = wp_get_archives('type=monthly&year=2016&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>
<h1>2015</h1>
<?php
$string = wp_get_archives('type=monthly&year=2015&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>
Ok, found a very helpful post on stack exchange: here
Basically, add this to functions.php:
//List archives by year, then month
function wp_custom_archive($args = '') {
global $wpdb, $wp_locale;
$defaults = array(
'limit' => '',
'format' => 'html', 'before' => '',
'after' => '', 'show_post_count' => false,
'echo' => 1
);
$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );
if ( '' != $limit ) {
$limit = absint($limit);
$limit = ' LIMIT '.$limit;
}
// over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride
$archive_date_format_over_ride = 0;
// options for daily archive (only if you over-ride the general date format)
$archive_day_date_format = 'Y/m/d';
// options for weekly archive (only if you over-ride the general date format)
$archive_week_start_date_format = 'Y/m/d';
$archive_week_end_date_format = 'Y/m/d';
if ( !$archive_date_format_over_ride ) {
$archive_day_date_format = get_option('date_format');
$archive_week_start_date_format = get_option('date_format');
$archive_week_end_date_format = get_option('date_format');
}
//filters
$where = apply_filters('customarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
$join = apply_filters('customarchives_join', "", $r);
$output = '<ul>';
$query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC $limit";
$key = md5($query);
$cache = wp_cache_get( 'wp_custom_archive' , 'general');
if ( !isset( $cache[ $key ] ) ) {
$arcresults = $wpdb->get_results($query);
$cache[ $key ] = $arcresults;
wp_cache_set( 'wp_custom_archive', $cache, 'general' );
} else {
$arcresults = $cache[ $key ];
}
if ( $arcresults ) {
$afterafter = $after;
foreach ( (array) $arcresults as $arcresult ) {
$url = get_month_link( $arcresult->year, $arcresult->month );
$year_url = get_year_link($arcresult->year);
/* translators: 1: month name, 2: 4-digit year */
$text = sprintf(__('%s'), $wp_locale->get_month($arcresult->month));
$year_text = sprintf('%d', $arcresult->year);
if ( $show_post_count )
$after = ' ('.$arcresult->posts.')' . $afterafter;
$year_output = get_archives_link($year_url, $year_text, $format, $before, $after);
$output .= ( $arcresult->year != $temp_year ) ? $year_output : '';
$output .= get_archives_link($url, $text, $format, $before, $after);
$temp_year = $arcresult->year;
}
}
$output .= '</ul>';
if ( $echo )
echo $output;
else
return $output;
}
And then call this function on the page:
<?php wp_custom_archive(); ?>
It will return a list exactly as needed, by year then month, with links to each!
<select name="archive-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
<option value=""><?php echo esc_attr( __( 'Select Month' ) ); ?></option>
<?php wp_get_archives( array( 'type' => 'monthly', 'format' => 'option', 'show_post_count' => 1 ) ); ?>
</select>
I would do it this way.
It's a bit shorter and easier to understand, and it relies on WP core functions, which is usually the preferable way to handle the data in WP. Also, it doesn't need expensive regex functions.
1. Add "in_year" option to the wp_get_archives() function
<?php
add_filter( 'getarchives_where', 'archives_in_specific_year', 10, 2 );
function archives_in_specific_year( $sql_where, $parsed_args ) {
if ( ! empty( $parsed_args['in_year'] ) ) {
$year = absint( $parsed_args['in_year'] );
$sql_where .= " AND YEAR(post_date) = $year";
}
return $sql_where;
}
?>
2. For each year, render that year and its months
<?php
$args = [
'type' => 'yearly',
'echo' => false,
];
$years = wp_get_archives( $args );
$years_array = explode( "\t", trim( wp_strip_all_tags( $years ) ) );
foreach ( $years_array as $current_year ) {
$current_year = intval( $current_year );
$monthly_args = [
'type' => 'monthly',
'format' => 'custom',
'echo' => false,
'before' => '<span>',
'after' => '</span>',
'in_year' => $current_year,
];
$months = str_replace( ' ' . $current_year, '', wp_get_archives( $monthly_args ) );
$yearly_args = [
'type' => 'yearly',
'after' => '<div>' . $months . '</div>',
'in_year' => $current_year,
];
wp_get_archives( $yearly_args );
}
?>
here's a simple mysql query, solved a similiar problem.
$query = 'SELECT DISTINCT MONTH(`post_date`) AS `month`, YEAR(`post_date`) AS `year` FROM `wp_posts` ORDER BY `post_date` ASC';
$results = $wpdb->get_results($query);
Getting the followoing error:
Warning: date() expects parameter 2 to be long, string given in
/home/users/2/catfood.jp-cybercat/web/academy/wp-includes/functions.php
on line 112
Which points to the line:
$datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
What changes are required to the above line to resolve this?
Here is the whole codes
function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
global $wp_locale;
$i = $unixtimestamp;
if ( false === $i ) {
if ( ! $gmt )
$i = current_time( 'timestamp' );
else
$i = time();
// we should not let date() interfere with our
// specially computed timestamp
$gmt = true;
}
/*
* Store original value for language with untypical grammars.
* See https://core.trac.wordpress.org/ticket/9396
*/
$req_format = $dateformatstring;
$datefunc = $gmt? 'gmdate' : 'date';
if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
$datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
$datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
$dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
$dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
$datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
$datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
$dateformatstring = ' '.$dateformatstring;
$dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
$dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
}
$timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
$timezone_formats_re = implode( '|', $timezone_formats );
if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
$timezone_string = get_option( 'timezone_string' );
if ( $timezone_string ) {
$timezone_object = timezone_open( $timezone_string );
$date_object = date_create( null, $timezone_object );
foreach( $timezone_formats as $timezone_format ) {
if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
$formatted = date_format( $date_object, $timezone_format );
$dateformatstring = ' '.$dateformatstring;
$dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
$dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
}
}
}
}
$j = #$datefunc( $dateformatstring, $i );
/**
* Filter the date formatted based on the locale.
*
* #since 2.8.0
*
* #param string $j Formatted date string.
* #param string $req_format Format to display the date.
* #param int $i Unix timestamp.
* #param bool $gmt Whether to convert to GMT for time. Default false.
*/
$j = apply_filters( 'date_i18n', $j, $req_format, $i, $gmt );
return $j;
}
$datefunc is an alias obviously to php's date method. If that's the case, you are trying to get the month from passing a single integer 1-12. When you can't do that, you need to pass a timestamp to PHP's date method then depending on the attributes you pass as options will return you the following data. Then you are passing it to wordpress locale get_month method that returns the name of the month. You need to refactor your code, so that $i isn't a for loop variable. If you are just trying to get Jan - Dec just do
$i = 1;
$monthArray = [];
do {
// Just push the months to an array and pass it to the view
array_push($monthArray, $wp_locale->get_month($i);
$i++;
} while($i < 13);
Then do what you need to with it. If you are getting a record back from the DB, you need to access the appropriate value in the returned model. Otherwise you're passing an array object. If you are accessing a model you should do)
// Access the property that you intended to retrieve the month on.
$datemonth = $wp_locale->get_month( $datefunc( 'm', $i['published_at'] ) );
I added a plugin called "paid membership pro" and this plugin was written in English and I translated into Japanese. There were lots of codes like this:
<?php printf(__('課金 #%s ( %s )', 'pmpro'), $pmpro_invoice->code, date_i18n(get_option('date_format'), $pmpro_invoice->timestamp));?>
I tried to change these codes as follows:
timestamp), $pmpro_invoice->code );?>
I guess that's why it caused the problem. What do you think?
Now I downloaded the plugin again and there is no problem.
Thank you for helping me.
I've been pulling my hair for hours for this. I'm trying to find all the positions of iframe The first occurrence is successful but not the second one.
Here's my code
$ofAllIFrames = qp( $this->content, 'iframe' );
$iframes = array();
$allIframes = array();
$startTag = 0;
foreach( $ofAllIFrames as $iframe) {
$startCurrentTag = strpos( $this->content, '<iframe>', $startTag );
$endCurrentTag = strpos( $this->content, '</iframe>', $startTag );
$iframes[] = array(
'start' => $startCurrentTag,
'end' => $endCurrentTag
);
$allIframes[] = $iframe;
$startTag = $endCurrentTag;
var_dump($startTag);
ob_flush();
}
return array(
'hasIFrame' => count( $allIframes ) > 0,
'elements' => $iframes
);
And this is my test case
public function test_if_content_has_multiple_iframes() {
$content = 'some content <iframe></iframe> <iframe id="1"></iframe> and another content';
$iframeChecker = new IFrame_Checker( $content );
$params = $iframeChecker->check();
$this->assertTrue( $params['hasIFrame'] );
$this->assertEquals( 13, $params['elements'][0]['start'] );
$this->assertEquals( 21, $params['elements'][0]['end'] );
$this->assertEquals( 31, $params['elements'][1]['start'] );
$this->assertEquals( 46, $params['elements'][1]['end'] );
}
And the test failed for the second iframe
1) Test_IFrame::test_if_content_has_multiple_iframes
Failed asserting that false matches expected 31.
$startCurrentTag = strpos( $this->content, '<iframe>', $startTag );
$endCurrentTag = strpos( $this->content, '</iframe>', $startCurrentTag );
Should work better.
Reason:
$startTag equals $endCurrentTag from the previous loop which refers to the offset at </iframe>.... So this is going to return the same position if you use $endCurrentTag = strpos( $this->content, '</iframe>', $startTag );