Git Product home page Git Product logo

flamingo's Introduction

Flamingo

This is the development repository for Flamingo, a WordPress plugin that stores messages collected through contact forms. A copy of the plugin package is downloadable from the WordPress.org Plugin Directory.

License

This plugin is released under the GNU General Public License Version 2 (GPLv2). For details, see license.txt.



Code is Poetry.

flamingo's People

Contributors

itpixelz avatar takayukister avatar zodiac1978 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

flamingo's Issues

Resend emails from Inbound Messages page

On sites that use SMTP or API methods for sending emails, sending may fail after the message is saved in Flamingo. When the problem is resolved, there's currently no way to resend them to the site admin and/or resend the confirmation message to the prospect.

Using information that's already captured by Flamingo (and Contact Form 7), however, this is possible to do, and will be well received by many plugin users worldwide.

Would you please consider implementing such a feature?

CSV export by URL (with E-Mail notifications)

I would like to use Flamingo so that users without a login can download a current CSV file of one CF7 form. I would send you a pull request. Do you want to incorporate it into your plugin or should I create a new plugin and (if needed) send you a pull request for new filters/hooks?

Here is my implementation plan for now (if you have thoughts about it, please let me know):

Extra "Additional Settings" of the CF7 Form:

  • flamingo_export_notify_email: [email protected], [email protected]
  • flamingo_access_token: ad43dadg234akogngw
  • flamingo_access_token_expires: 2021-09-01 10:00:00 GMT
  • flamingo_access_token and flamingo_access_token_expires are generated automatically if not present and flamingo_export_notify_email is not empty. (Users can change it manually afterwards if they want, and the expiry time uses a wordpress filter to allow custom values, by default maybe 7 days.)

At form submission, an E-Mail is sent that contains:

  • the name of the form
  • the number of entries that are stored for this form
  • a link to the CSV export
  • the date how long this link is valid

When the URL is called:

  • If the access token is valid, matches the form id in the URL & is not expired: send the CSV file
  • If the access token is not valid or expired: Show an error page: "The access token is invalid. A reminde E-Mail with the valid access token has been sent to the given E-Mail adress."
    (For security reasons, the E-Mail adress can only be changed in the CF7 form itself.)

Prepare for 2.4 release

  • Add 2.4 change log to readme.txt
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.4
  • Update Tested up to in readme.txt to 6.2
  • Update Stable tag in readme.txt to the current stable version (2.3)
  • Create 2.4 release on Github
  • Create 2.4 release on WordPress.org SVN

Prepare for 2.5 release

  • Add 2.5 change log to readme.txt
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.5
  • Update Tested up to in readme.txt to 6.5
  • Update Stable tag in readme.txt to the current stable version (2.4)
  • Create 2.5 release on Github
  • Create 2.5 release on WordPress.org SVN

Use Flamingo_Inbound_Message::find()

Related issue: #2

You can use Flamingo_Inbound_Message::find() to improve drastically some inefficient parts seen in flamingo_schedule_move_trash().

  1. In the SQL query in flamingo_schedule_move_trash(), there are no post_type and post_status specified. If by any chance another plugin or WordPress itself uses the same meta key '_spam_meta_time', it will lead to a severe conflict.
  2. The meta value '_spam_meta_time' remains after the post is trashed, so the post will be included in the result of the SQL query repeatedly.
  3. No upper limit of posts is specified in the SQL query, so it might be an abnormally large number causing a time-out.

You can use Flamingo_Inbound_Message::find() like this:

function flamingo_schedule_move_trash() {

	// abort if FLAMINGO_MOVE_TRASH_DAYS is set to zero or in minus
	if ( (int) FLAMINGO_MOVE_TRASH_DAYS <= 0 ) {
		return true;
	}

	$posts_to_move = Flamingo_Inbound_Message::find( array(
		'posts_per_page' => 100,
		'meta_key' => '_spam_meta_time',
		'meta_value' => time() - ( DAY_IN_SECONDS * FLAMINGO_MOVE_TRASH_DAYS ),
		'meta_compare' => '<',
		'post_status' => Flamingo_Inbound_Message::spam_status,
	) );

	foreach ( $posts_to_move as $post ) {

		if ( $post->trash() ) {
			// delete spam meta time to stop trashing in cron job
			delete_post_meta( $post->id, '_spam_meta_time' );
		}

	}
}

It is advisable to avoid using SQL where possible.

Prepare for 2.2.3 release

  • Update Stable tag in readme.txt to the current stable version (2.2.2)
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.2.3
  • Add 2.2.3 change log to readme.txt

JSON overflows out of reCAPTCHA meta-box

The reCAPTCHA meta-box, introduced in Flamingo 2.0, has a field for JSON-encoded response from reCAPTCHA API. When the value of the field is long and the screen width of browser is short, the content overflows out of the meta-box.

screenshot of the issue

There can be two approaches to address this issue. 1) Modify with CSS, 2) Insert whitespaces in appropriate places to prompt line feeds. I prefer the second approach.

You can insert whitespaces into JSON by giving the JSON_PRETTY_PRINT constant as the second parameter ("options") of json_encode(). This requires PHP 5.4.0+, so we need to change the "Requires at least" version to WordPress 5.2 (because minimum PHP supported is 5.6.20) or specify the "Requires PHP" header in the readme.txt file.

I feel we can/should raise the "Requires at least" to 5.2 in the next release.

Dashboard widget

Made a dashboard widget to show latest emails

//Add custom dashboard widget

function my_custom_dashboard_widgets() {
 wp_add_dashboard_widget('my_show_latest_emails', 'Latest Emails', 
'my_show_latest_emails');
}
add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');


//function to get emails
function my_show_latest_emails() {

echo '<div id="activity-widget">';

$args = array(
    'numberposts' => 10,
    'offset' => 0,
    'category' => 0,
    'orderby' => 'post_date',
    'order' => 'DESC',
    'include' => '',
    'exclude' => '',
    'meta_key' => '',
    'meta_value' =>'',
    'post_type' => 'flamingo_inbound',
    'post_status' => 'publish',
    'suppress_filters' => true
);

$recent_emails = wp_get_recent_posts( $args, ARRAY_A );

if($recent_emails)
{
    echo '<table><thead><th>Date</th><th>Email</th></thead><tbody>';
    foreach($recent_emails as $email){
        echo '<tr>';
        echo '<td>' . $email->post_date . '</td>';
        echo '<td>' . $email->post_title . '</td>';
        echo '</tr>';

    }
    echo '</tbody></table>';
}

if ( !$recent_emails) {
    echo '<div class="no-activity">';
    echo '<p class="smiley"></p>';
    echo '<p>' . __( 'No activity yet!' ) . '</p>';
    echo '</div>';
}

echo '</div>';
}

Prepare for 2.3 release

  • Update Stable tag in readme.txt to the current stable version (2.2.3)
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.3
  • Add 2.3 change log to readme.txt
  • Create 2.3 release on Github

Add hook to create more filter options

Would love a hook to add more filtering options to the admin screen, so you could filter incoming messages by year, week, day or a custom date span even.

Perhaps a hook on the args that are passed to WP_Query would be enough? And the ability to somehow add more <select> elements in the admin too. But just being able to filter by URL would be fine for now.

Prepare for 2.2.1 release

  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.2.1
  • Update Tested up to in readme.txt to 5.6
  • Update Stable tag in readme.txt to the current stable version (2.2)
  • Add 2.2.1 change log to readme.txt

Cron job initialization

It seems that the wp action is only executed on the front end of the website (and additionally i believe we don't need to fire an action each page load for that).

https://github.com/takayukister/flamingo/blob/7f9065e8dcb71500f28775116be912f340f32536/includes/cron.php#L9-L20

To give a try just replace the content of flamingo_schedule_activation with die(); then reload the page website and wordpress admin and only the frontend will result into a white page.

Then replace the hook wp with admin_init and retry (result: white page for admin but not for front facing pages).

Make properties private

In class definitions in includes/class-*.php there are public properties that are not necessarily to be public. They should become private for secure use.

Add retention period setting

Flamingo would benefit from offering the possibility of automatically deleting messages and personal data after a certain period. With new legislation, like GDPR in the EU, keeping personal data in the database forever could represent a security breach.

Gravity Form has this functionality. The same for WP Mail SMTP, which has this setting:

image

Slowness with tens of thousands of submissions(!)

A client of ours has heavily used contact forms using cf7 and flamingo.
The admin page "Address Book" was VERY slow (many seconds!)

It seemed to spend a lot of time in Flamingo_Contacts_List_Table->column_history()

There is a LOOP which does a FIND for matching messages.
I have speeded it up by doing get_objects_in_term() and using post__in instead of searching by slug, specifying just ids for fields, and using none for orderby as we are just after the count.

I hope this may be useful?

                // Contact channels
		$terms = get_terms( Flamingo_Inbound_Message::channel_taxonomy );

		if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
			foreach ( (array) $terms as $term ) {
                // !!! get ALL posts in using the TERM, these are the messages we want
                $objects = get_objects_in_term($term->term_id, Flamingo_Inbound_Message::channel_taxonomy );
				Flamingo_Inbound_Message::find( array(
					//'channel' => $term->slug, // !!!
					's' => $item->email,
                    'fields'=> 'ids', // !!! want just ids so we can count
                    'post__in' => $objects, // !!!
                    'orderby' => 'none', // !!! don't bother trying to order, we just want count!
				) );

				$count = (int) Flamingo_Inbound_Message::count();

				if ( ! $count ) {
					continue;
				}

Also, the contact forms were VERY SLOW to SUBMIT (over a minute!)

Flamingo_Inbound_Message->save() relies on WordPress to ensure unique post SLUGS, which works by checking for the specified slug and if found, appending a suffix and try again, if that is found then try the next suffux up, and so on.
When there are tens of thousands of submissions of the same form, this means tens of thousands of queries, which takes a while!

We can speed this up by using ONE QUERY to find the LARGEST suffix in use, and using the next one up, or if none then suffix "2" (the WordPress code seems to start with suffix 2)
If we specify the POST_NAME as an argument for wp_insert_post() then WordPress won't do the check.

              if ( $this->timestamp
		and $datetime = date_create( '@' . $this->timestamp ) ) {
			$datetime->setTimezone( wp_timezone() );
			$postarr['post_date'] = $datetime->format( 'Y-m-d H:i:s' );
		}

        /* !!! if there are tens of thousands of posts with the SAME TITLE
        * and we DON'T SPECIFY a post_name (slug) here
        * we will have to loop through the posts with that name ONE AT A TIME
        * until we get to a name which doesn't exist yet
        */
       // Post slugs must be unique across all posts.
       global $wpdb;
       $slug = sanitize_title($postarr['post_title']);
       $post_type = $postarr['post_type'];
       $post_id = $postarr['ID'];
       $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
       $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
       if($post_name_check) {
           // we have a post with that name already
           $suffix = 2;
           $alt_post_name = $slug.'-';
           // find the BIGGEST suffix from the DB
           $check_sql = "SELECT CAST(SUBSTRING(post_name,LENGTH(%s)+1) AS INTEGER) FROM $wpdb->posts WHERE post_name LIKE %s AND post_type=%s AND ID != %3d ORDER BY 1 DESC LIMIT 1";
           $post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $alt_post_name.'%', $post_type, $post_ID ) );
           if($post_name_check) {
               $suffix = absint($post_name_check)+1; // number from DB plus one
           }
           $slug .= '-'.$suffix; // either next suffix from DB or 2
           $postarr['post_name'] = $slug;
       } else {
           // we DONT have a post with that name already, and can save a db query later by specifying the name here
           $postarr['post_name'] = $slug;
       }

		$post_id = wp_insert_post( $postarr );

Export is showing date in UTC (not local) time

First reported here: https://wordpress.org/support/topic/export-is-showing-date-in-utc-not-local-time/

I was wondering that the CSV shows UTC time instead of local time, although the list table is showing a local time.

After digging in the code I found get_post_time in /admin/admin.php wit the GMT parameter set to true:
$row[] = get_post_time( 'c', true, $item->id ); // Date

I think the second parameter (GMT) should be changed to false to switch to local time (or you could add a filter, so we could easily change it if needed without breaking running workflows).

As an alternative you could add another column and add local time there to not break backwards compatibility.

Related: https://developer.wordpress.org/reference/functions/get_post_time/

Thanks for considering!

Avoid PHP warnings

See https://wordpress.org/support/topic/changing-status-to-spam-throws-errors/

Warning: array_merge(): Argument #2 is not an array in /path-to-my-domain-removed-here/wp-content/plugins/flamingo/includes/class-inbound-message.php on line 210

There may be data created by an old version of Flamingo that didn't support the consent property yet. The following array_merge() arguments should be properly casted to arrays.

$post_content = array_merge(
  $this->fields,
  $this->consent,
  $this->meta
);

Prepare for 2.2 release

  • Update Requires at least in readme.txt to 5.4
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.2
  • Update Tested up to in readme.txt to 5.5
  • Update Stable tag in readme.txt to the current stable version (2.1.1)
  • Add 2.2 change log to readme.txt

Typo

image

I see a typo. flamigo is written instead of flamingo, language is Turkish

Update readme.txt for 2.1 release

Update readme.txt following the Plugin Handbook.

Usually you only need to update 3 numbers in the header section ("Requires at least", "Tested up to", and "Stable tag") and the Changelog section.

Note:

  • "Tested up to" should refer to the major version number of WordPress, so it should be "5.2" now (not "5.2.3").
  • You don't have to keep old change-logs. Keeping ones for the current major version and last one major version is enough. So, it's OK to remove the change-log for 1.9.

Prepare for 2.2.2 release

  • Update Stable tag in readme.txt to the current stable version (2.2.1)
  • Update Version and the FLAMINGO_VERSION constant in flamingo.php to 2.2.2
  • Update Tested up to in readme.txt to 5.8
  • Add 2.2.2 change log to readme.txt

CSV Vulnerabilities

https://www.contextis.com/en/blog/comma-separated-vulnerabilities

This issue was first reported in 2014. As you may notice soon, the vulnerabilities exist in the behavior of spreadsheet applications like Microsoft Excel, Apache OpenOffice, and LibreOffice, not in this WordPress plugin. What we can do is only mitigating the risk a bit in the CSV exporting.

The linked post suggests prefixing suspicious fields with a single-quotation mark, but I think it is not enough informative. Instead of a simple quotation, we should add a sentence at the beginning of each field, say, [It is possible that a maliciously crafted formula is injected into this field. For details, see https://....]

Add UTF-8 BOM to CSV export to fix MS Excel encoding issues

After exporting a CSV and opening it in Microsoft Excel the encoding is wrong. ÅÄÖ etc looks scrambled.

Adding BOM apparently fixes this issue.

Would you consider either:

  1. Adding BOM by default
  2. Adding a do_action('flamingo_pre_csv') at the beginning of the CSV file so we can add it ourselves?

Thank you

Spam to Trash: Make the feature customizable

Related issue: #2

Some users may not want to trash items automatically, or may want to change the days from the default 30.

Let's define the constant like the following so that users can override the value in their wp-config.php file.

if ( ! defined( 'FLAMINGO_MOVE_TRASH_DAYS' ) ) {
	define( 'FLAMINGO_MOVE_TRASH_DAYS', 30 );
}

Also, let's check the FLAMINGO_MOVE_TRASH_DAYS constant in flamingo_schedule_move_trash(), and if the value is 0, abort the trashing process.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.