/**
  * Inject speed bumps into a block of text, like post content.
  *
  * Can be called directly, like `Speed_Bumps()->insert_speed_bumps( $post->post_content );`.
  *
  * More common usage is by adding this function to a filter:
  * `add_filter( 'the_content', array( Speed_Bumps(), 'insert_speed_bumps' ), 1 );`
  * (Note the early priority, as it should be attached before `wpautop` runs.)
  *
  * @param string $the_content A block of text. Expected to be pre-texturized.
  * @return string The text with all registered speed bumps inserted at appropriate locations if possible.
  */
 public function insert_speed_bumps($the_content)
 {
     $output = array();
     $already_inserted = array();
     $parts = Text::split_paragraphs($the_content);
     $total_paragraphs = count($parts);
     foreach ($parts as $index => $part) {
         $output[] = $part;
         $context = array('index' => $index, 'prev_paragraph' => $part, 'next_paragraph' => $index + 1 < $total_paragraphs ? $parts[$index + 1] : '', 'total_paragraphs' => $total_paragraphs, 'the_content' => $the_content, 'parts' => $parts);
         foreach ($this->get_speed_bumps() as $id => $args) {
             if (apply_filters('speed_bumps_' . $id . '_constraints', true, $context, $args, $already_inserted)) {
                 $content_to_be_inserted = call_user_func($args['string_to_inject'], $context, $already_inserted);
                 $output[] = $content_to_be_inserted;
                 $already_inserted[] = array('index' => $index, 'speed_bump_id' => $id, 'inserted_content' => $content_to_be_inserted);
             }
         }
     }
     return implode(PHP_EOL . PHP_EOL, $output);
 }