0

I'm trying to develop a plugin which adds a single line to the .htaccess file generated by WordPress.

The problem is that one of the WP generated lines override my rule, and via the "insert_with_markers()" function, I have not found a way to specify a position so I could prepend my line instead of appending it as currently is happening.

The first line of code is the auto generated WordPress line, and the second one is the one I'd like to have working.

RewriteRule . /dev/index.php [L]

RewriteRule ^article/([/_0-9a-zA-Z-]+)$ http://www.domain.tld/?id=$1 [R=301,L,NC]

The way I see it there's 2 possibilities here:

A) Somehow specify where the insert_with_markers() places the new line of code, or

B) Modify my RewriteRule to work together with the WordPress generated one.

I hope you can point me a step or two closer to the right path.

Thanks!

0

I would suggest an alternative route: the rewrite API - did you know it supports external URLs*?

function wpse_199898_add_htaccess_rule() {
    // No need for the caret "starts with", WP will add it
    add_rewrite_rule( 'article/([/_0-9a-zA-Z-]+)$', 'http://www.domain.tld/?id=$1 [R=301,L,NC]' );
}

add_action( 'init', 'wpse_199898_add_htaccess_rule' );

*Almost. We just need a fix for WP's quirky path prefixing:

function wpse_199898_fix_htaccess_rule( $rules ) {
    return str_replace( '/http://www.domain.tld/', 'http://www.domain.tld/', $rules );
}

add_filter( 'mod_rewrite_rules', 'wpse_199898_fix_htaccess_rule' );
| improve this answer | |
  • Thanks, I was gonna do some more digging around the filters and so on, but seems like the rewrite API seems to be exactly what I need, and these examples look great so I'll accept your answer. – Mark Aug 27 '15 at 13:48
0

After reading up on the issue I decided to go a different route altogether, and hook into filters instead of using insert_with_markers()

| improve this answer | |
0

If anyone else wanted some function for .htaccess code insert, copy WordPress function from this core Wordpress file: wp-admin/includes/misc.php:

line 109: function insert_with_markers( $filename, $marker, $insertion ) {

Just for reference here is function:

if ( ! function_exists( 'insert_with_markers' ) ) {
    function insert_with_markers( $filename, $marker, $insertion ) {
    if ( ! file_exists( $filename ) ) {
        if ( ! is_writable( dirname( $filename ) ) ) {
            return false;
        }

        if ( ! touch( $filename ) ) {
            return false;
        }

        // Make sure the file is created with a minimum set of permissions.
        $perms = fileperms( $filename );
        if ( $perms ) {
            chmod( $filename, $perms | 0644 );
        }
    } elseif ( ! is_writeable( $filename ) ) {
        return false;
    }

    if ( ! is_array( $insertion ) ) {
        $insertion = explode( "\n", $insertion );
    }

    $switched_locale = switch_to_locale( get_locale() );

    $instructions = sprintf(
        /* translators: 1: Marker. */
        __(
            'The directives (lines) between `BEGIN %1$s` and `END %1$s` are
dynamically generated, and should only be modified via WordPress filters.
Any changes to the directives between these markers will be overwritten.'
        ),
        $marker
    );

    $instructions = explode( "\n", $instructions );
    foreach ( $instructions as $line => $text ) {
        $instructions[ $line ] = '# ' . $text;
    }

    /**
     * Filters the inline instructions inserted before the dynamically generated content.
     *
     * @since 5.3.0
     *
     * @param string[] $instructions Array of lines with inline instructions.
     * @param string   $marker       The marker being inserted.
     */
    $instructions = apply_filters( 'insert_with_markers_inline_instructions', $instructions, $marker );

    if ( $switched_locale ) {
        restore_previous_locale();
    }

    $insertion = array_merge( $instructions, $insertion );

    $start_marker = "# BEGIN {$marker}";
    $end_marker   = "# END {$marker}";

    $fp = fopen( $filename, 'r+' );
    if ( ! $fp ) {
        return false;
    }

    // Attempt to get a lock. If the filesystem supports locking, this will block until the lock is acquired.
    flock( $fp, LOCK_EX );

    $lines = array();
    while ( ! feof( $fp ) ) {
        $lines[] = rtrim( fgets( $fp ), "\r\n" );
    }

    // Split out the existing file into the preceding lines, and those that appear after the marker.
    $pre_lines        = array();
    $post_lines       = array();
    $existing_lines   = array();
    $found_marker     = false;
    $found_end_marker = false;
    foreach ( $lines as $line ) {
        if ( ! $found_marker && false !== strpos( $line, $start_marker ) ) {
            $found_marker = true;
            continue;
        } elseif ( ! $found_end_marker && false !== strpos( $line, $end_marker ) ) {
            $found_end_marker = true;
            continue;
        }
        if ( ! $found_marker ) {
            $pre_lines[] = $line;
        } elseif ( $found_marker && $found_end_marker ) {
            $post_lines[] = $line;
        } else {
            $existing_lines[] = $line;
        }
    }

    // Check to see if there was a change.
    if ( $existing_lines === $insertion ) {
        flock( $fp, LOCK_UN );
        fclose( $fp );

        return true;
    }

    // Generate the new file data.
    $new_file_data = implode(
        "\n",
        array_merge(
            $pre_lines,
            array( $start_marker ),
            $insertion,
            array( $end_marker ),
            $post_lines
        )
    );

    // Write to the start of the file, and truncate it to that length.
    fseek( $fp, 0 );
    $bytes = fwrite( $fp, $new_file_data );
    if ( $bytes ) {
        ftruncate( $fp, ftell( $fp ) );
    }
    fflush( $fp );
    flock( $fp, LOCK_UN );
    fclose( $fp );

    return (bool) $bytes;
}
}

Now you can call it with your .htaccess code like this:

      if (is_file(ABSPATH . '.htaccess')) {
                $htaccess = ABSPATH . '.htaccess';
                $lines = array();


                $Rulesstring = '
                <filesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|svg|js|css|swf)$">
                Header set Cache-Control "max-age=31536000, public"
                </filesMatch>
                ';

                $lines = explode( "\n", $Rulesstring );

                insert_with_markers($htaccess, "HelloFood", $lines);
      }
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.