Author: Zarina

  • Limiting the number of password attempts in the web login form using Nginx or HAProxy by way of example of WordPress

    By the example of WordPress consider a method for enhancing security by limiting the number of HTTP-requests to the form of entering the password. This helps protect against brute force published a blog (search and crack the password by trying all possible scenarios of a particular set of characters, or the selection of a dictionary of common passwords). This method, in principle, can be used to protect other Web applications.

    The task can be realized using Nginx module ngx_http_limit_req_module [1] acts as a front-end to the Apache Web server or FastCGI, or via HAProxy [2, 3], acts as a load balancer in front of web servers.

    In both cases, the algorithm works as follows. When authentication browser refer to the addresses containing the substring “/wp-login.php”. It is necessary to keep track of it and to limit the number of requests from the same IP without affecting circulation to all other addresses. Block settings must be chosen in such way as not to create a normal user inconvenience. Especially attentively should be configured to lock when the authorization form uses a large number of users with the same IP-address.

    Method №1: Nginx

    http {
    <...>
    
    limit_req_zone $binary_remote_addr zone=login:10m rate=15r/m;
    
    server {
    listen 80;
    server_name frontend.example.org;
    
    location ~* /wp-login.php {
    limit_req zone=login burst=4;
    proxy_pass http://backend:8080;
    <...>
    }
    
    location / {
    proxy_pass http://backend:8080;
    <...>
    }
    }

    Block settings:

    limit_req_zone $binary_remote_addr zone=login: 10m rate=15r/m; Sets an area of shared memory, which stores the state for different IP-addresses. In our case, the state is stored in the zone “login” size of 10 megabytes, and the average speed of query processing for the zone can not exceed 15 requests per minute. The processing speed can be specified in requests per second (r/s) or requests per minute (r/m).

    limit_req zone=login burst=4; sets the login area and the maximum size of the burst of requests. If the requests rate higher than described in the area, their processing is delayed so that the request is being processed at a given speed. Excessive requests are delayed as long as their number does not exceed the maximum size of the burst. When exceeding the request fails with the error 503.

    Method №2: HAProxy

    In this section of the backend, serving our blog, add the following lines [2]:

    tcp-request inspect-delay 10s
    tcp-request content accept if HTTP
    # brute force protection
    acl wp_login path_beg -i /wp-login.php
    stick-table type binary len 20 size 500 store http_req_rate(20s) peers local
    tcp-request content track-sc2 base32+src if METH_POST wp_login
    stick store-request base32+src if METH_POST wp_login
    acl bruteforce_detection sc2_http_req_rate gt 5
    acl flag_bruteforce sc1_inc_gpc0 gt 0
    http-request deny if bruteforce_detection flag_bruteforce
    

    Upon detection of POST-request to the page /wp-login.php saved hash of three elements: header HTTP Host, URL-path and IP source. Identified on the basis of the hash the user can make requests for five to 20 seconds, the sixth request will be blocked.

    Sourses

    1. Module ngx_http_limit_req_module – nginx.org
    2. http://blog.haproxy.com/2013/04/26/wordpress-cms-brute-force-protection-with-haproxy/ – blog.haproxy.com
    3. Better Rate Limiting For All with HAProxy – blog.serverfault.com

    This text is a translation of the article “Ограничение количества попыток ввода пароля в веб-форме авторизации при помощи Ngnix или HAProxy на примере WordPress” published by foboss on habrahabr.ru.

    Anti-Spam by CleanTalk.

  • 7 useful functions Drupal API that everyone should know!

    In this article we will look at 7 Drupal API functions that are very helpful in the development of sites to Drupal 7.

    check_plain($text) – re-encodes special characters to HTML entities.

    Parameters:

    • $text – the string for conversion

    The return value: the processed string to display as HTML.

    This function can be used to treat all kinds of data coming to the site from a variety of sources: user input, import data from another site, Twitter, etc.

    t($string, array $args = array(), array $options = array()) – converts the string to the user-selected language.

    Parameters:

    • $string – the string to be translated
    • $args – an associative array of wildcard patterns (placeholders)
    • $options – an associative array of additional options, contains two possible options: langcode – a clear indication of the language code that you want to translate a string, context – allows you to set the context of translation.

    The return value: the translated string.

    Example of the function t():

    t('Good afternoon, @first_name @last_name. ', array('@first_name' => 'Jhon', '@last_name' => 'Smith')); // Returns 'Good afternoon, Jhon Smith.'

    There are three types of wildcard patterns:

    • !name – value is substituted without processing
    • @name – value processed by the function check_plain, all HTML tags are cut
    • %name – value processed by the function theme_placeholder (also that check_plain, but the result is wrapped in a tag <em>)

    format_plural($count, $singular, $plural, array $args = array(), array $options = array()) – creates a string containing quantitative value.

    Parameters:

    • $count – quantitative value
    • $singular – a string that will be used if $count == 1
    • $plural – a string that will be used if $count > 1
    • $args – an associative array of of wildcard patterns (placeholders)
    • $options – the same as in the t() function

    The return value: a string translated by using the function t(), depending on the parameter $count selected string that will be used for translation.

    Example:

    $comment_count=1;
    format_plural($comment_count, '1 comment', '@count comments'); // return '1 comment'
    
    $comment_count=5;
    format_plural($comment_count, '1 comment', '@count comments'); // return '5 comments'

    drupal_get_title() – returns the current page title.

    This function can be used in combination with drupal_set_title() to process the header and install a new one.

    drupal_set_title($title = NULL, $output = CHECK_PLAIN) – sets the title of the page.

    Parameters:

    • $title – a string that will be used as the title of the page
    • $output – a flag that determines whether the $title processed by function check_plain().

    The return value: updated page title.

    url($path = NULL, array $options = array()) – forms an internal or external URL.

    Parameters:

    • $ path – internal relative or external absolute path
    • $ options – an associative array of options:
      • query- array passed parameters such as key/value
      • fragment – the anchor element on the page
      • absolute – flag (default FALSE) if set to TRUE then the url will be defined as an absolute.
      • alias – the flag (default FALSE) if set to TRUE then the path will be regarded as an alias (this will not be accomplished in the search for the alias database that will speed up)
      • external – the flag, if set to TURE url will be regarded as external.
      • language – a language object defines the language to find an alias selected language
      • https – the flag is set to TRUE if the path will be https protocol, if FALSE, then the http.
      • base_url – the value to replace the standard base path
      • prefix – the prefix path language

    The returned value: formed URL.

    drupal_goto($path = ”, array $options = array(), $http_response_code = 302) – produces redirect the user to another page.

    Parameters:

    • $path – relative or absolute path to be produced redirect
    • $options – the list of options as a function of the url()
    • $http_response_code – code status code

    This text is a translation of the article “7 полезных функций Drupal API который должен знать каждый!” published on drupal-learning.com.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • Drupal API functions for working with taxonomy

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    In Drupal API there are a number of useful features for taxonomy that provide nodes, classified on the definition terms, and let you know parent or child terms, etc.

    Load the object of the term by its tid

    Function taxonomy_term_load() by analogy with node_load() returns an object of the term by tid:

    <?php
      $term = taxonomy_term_load(1);
      print $term->name; // the name of the term
      print $term->vid; // taxonomy vocabulary identifier to which the term belongs
    ?>

    By analogy with node_load_multiple() in Drupal API there is a function taxonomy_term_load_multiple()

    Find terms by name

    To download terms by their names is a function taxonomy_get_term_by_name(), which returns an array of terms with the given name.

    Get all vocabulary terms

    To get all vocabulary terms with the hierarchy, you can use the taxonomy_get_tree(), where you want to pass a value vid – ID taxonomy vocabulary. In this case, the function returns objects with additional properties terms “depth” (the depth of the term in the hierarchy) and “parents” – an array of values tid parent terms. Sample code to display a “tree” vocabulary you will find on the page description of the function.

    Gets the child terms

    A fairly common task – to get the child terms specified term. For its solution is the function taxonomy_get_children(). Note that this function takes the tid of the term, and returns the full facilities of child terms (if any). That is not appropriate to use this feature, if we want, for example, only the values tid or name of child terms. In such situations, for performance reasons should write a request to the site database using db_select() (the basis of a request can be taken from the body of the function taxonomy_get_children()).

    Gets the parent terms

    For the parents given the term in the API Drupal 7 provides two functions – taxonomy_get_parents() and taxonomy_get_parents_all().

    Despite nearly identical names, the functions differ substantially. The first return only “parents” specified term. Suppose we have a dictionary “Electronics”, it parental terms Sony and Panasonic, and the term “TV”, which is made as a child for Sony, as well as for Panasonic. Then the function call taxonomy_get_parents() by substituting into it the values tid of the term “TV” we get objects terms Sony and Panasonic.

    The second function returns objects of “ancestors” of the term, and not only his parents, ie taking into account the entire depth of the vocabulary.

    Load all the nodes of the term

    For content classified by definition of the term, is a function taxonomy_select_nodes(). When all the evidence of her appointment beginners sometimes have problems associated with failure to take into account all the arguments of the function. So let’s look at an example. Suppose the term with tid = 1 is assigned 25 nodes. Then it is logical to assume that the line of code:

    <?php
      $nids = taxonomy_select_nodes(1);
    ?>

    returns an array of 25 elements – nid of nodes. However, it is not. Pay attention to the second argument, namely boolean variable $pager, the default to TRUE. This means that our sample will be divided by page. If we want to get all the nodes of the term on the same page, we need to convert the line of the code in:

    <?php
      $nids = taxonomy_select_nodes(1, false);
    ?>

    Also, when using the taxonomy_select_nodes(), you can set a limit on the number of loaded nodes and set the sort order by the parameters $limit and $order.

    In conclusion, it is worth mentioning such useful features as taxonomy_get_vocabularies() – to download all the vocabularies taxonomy and its simplified version taxonomy_vocabulary_get_names(), which returns an array of objects, properties which are names, machine names and identifiers vid vocabularies.

    This text is a translation of the article “Функции Drupal API для работы с таксономией” published by Sergey Belyaev on sergeybelyaev.name.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • A few tips to accelerate Drupal

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    Drupal constantly criticized for its slowness, for the great number of database requests and clumsiness. Most often it is solved by using Memcached or Varnish. In this article I would like to add a few more tips, the use of which will not make Drupal even slower. Those who are interested, please welcome under the cut.

    Use JS module

    Together with the functionality of the site is growing and the number of consumed memory and the number of SQLrequests needed to perform a full load Drupal. If you need to do only one SQL request using AJAX, Drupal can spend a lot of time to fully load and execute code that may never be used in the request. JS module solves this problem by providing an alternative way to download Drupal only to the level required for a specific task. Including allowing you to connect the necessary files and modules to handle the request.

    Drupal loads itself with each request through a series of phases of the boot. All phases of the download are defined in the file bootstarp.inc:

    • DRUPAL_BOOTSTRAP_CONFIGURATION: In this phase filled an internal array of configurations Drupal, set the base URL, analyze settings.php file, etc.
    • DRUPAL_BOOTSTRAP_PAGE_CACHE: An attempt to provide a page from the cache, if enabled page caching for anonymous users.
    • DRUPAL_BOOTSTRAP_DATABASE: Determine the type of database and the connection to request the database.
    • DRUPAL_BOOTSTRAP_VARIABLES: Initialization of variables.
    • DRUPAL_BOOTSTRAP_SESSION: Initialization treatment of sessions.
    • DRUPAL_BOOTSTRAP_PAGE_HEADER: Setting the page title.
    • DRUPAL_BOOTSTRAP_LANGUAGE: Definition of the language of the page.
    • DRUPAL_BOOTSTRAP_FULL: Loading modules and initialization of issues.

    For example, if you only need to use the function variable_get () in the AJAX callback will be enough level DRUPAL_BOOTSTRAP_VARIABLES, and if you need access to the current user object $user you need to use DRUPAL_BOOTSTRAP_SESSION etc.

    To work with the module JS enough to realize hook_js (), in which to describe what modules you need to connect, what phase of the bootstrap to use:

    /**
     * Implements hook_js().
     */
    function js_example_js() {
      return array(
        'results' => array(
          'callback' => 'js_example_ajax_results', // The callback function is required to display the results
          'includes' => array('unicode', 'locale', 'language'), // Which files to download from a directory /includes
          'dependencies' => array(), // List of modules to be loaded
          'bootstrap' => DRUPAL_BOOTSTRAP_DATABASE, // Required loading phase Drupal
          'file' => 'js_example.ajax.inc', // File that contains the callback
          'access callback' => 'js_example_ajax_results_access', // The callback function to check the access rights
          'access arguments' => array(), // The argument list for the access callback
          'page arguments' => array(), // The argument list for the callback
          'skip_hook_init' => TRUE, // A flag that allows you to skip the execution hook_init(),
          'i18n' => FALSE, // A flag that lets you enable or disable support for i18n
        ),
      );
    }
    

    It is important to understand that it is quite difficult to perform the control of access rights in the initial stages of loading Drupal, so it is necessary to closely monitor the security of their code.

    Loading entities

    It is often necessary to add fields from the user profile in the node and the most simple solution for this use the hook template_preprocess_node():

    template_preprocess_node(&$variables){
    $node = $variables['node'];
    $variables['account'] = user_load($node->uid);
    }

    But when displaying a large number of nodes, this approach will create a large number of database requests. Get the same functionality without sacrificing performance by using the hook hook_entity_prepare_view():

    hook_entity_prepare_view($entities, $type, $langcode{
      if ($type != 'node') {
        return;
      }
      $uids = array();
      foreach ($entities as $entity) {
        $uids[] = $entity->uid;
      }
      $accounts = user_load_multiple($uids);
      foreach ($entities as $entity) {
        $entity->account = $accounts[$entity->uid];
      }
    }
    

    After that, $ entity-> account will be available in preprotsesse:

    template_preprocess_node(&$vars) {
      $account = $vars['node']->account;
    }
    

    Use drupal_static()

    When the code is executed multiple times during a single request, it is very convenient to use static variables to cache (more on static variables in PHP can be found here and here). Drupal core provides an excellent solution for the realization of static caching – function drupal_static(). Function drupal_static() provides a central static variable to store data. The first call drupal_static () returns NULL, but any changes in this variable will be saved for the next call to this function. This way we can check whether the variable is already installed and get it instantly without doing almost no work at the same time.

    function my_module_function() {
      $foo = &drupal_static(__FUNCTION__);
      global $user;
      if (!isset($foo[$user->uid])) {
        $foo[$user->uid] = something_expensive();
      }
      return $foo[$user->uid];
    }
    

    Frequent use of variable_set () affect performance

    Variables in Drupal are stored in a special table in the format: name – the serialized value. For each request, all variables are loaded from the cache in the global variable $conf.

    During saving of each variable the following happens:

    • The record is updated in the database
    • Ceared cache
    • When the next request finds that there is no cache for table variables, all variables are loaded and stored in the cache.

    With a large number of variables it can take a lot of time. In Drupal is realized locking system and any long-running operations in parallel which, most likely, will come other requests should try before work to get a lock. If the previous request to clear the cache variables, the following request will rebuild it, so it is very frequent use functions variable_set() can lead to mass table lock, due to the fact that tens of requests waiting for a new record cache table of variables that can become out of date before it will extract for use.

    Reduction of the table sessions

    Drupal stores user sessions in the database instead of files, so if a site with a large attendance, this table can quickly grow to enormous size. If the table session was very large, you can increase the frequency of garbage collection for PHP-sessions in settings.php:

    ini_set('session.gc_maxlifetime', 86400); 
    

    I hope that not all of this list is just too obvious things and this is useful to someone.

    This text is a translation of the article “Несколько советов по ускорению Drupal” by afi13 published on habrahabr.ru.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • Saving “many-to-many” in Yii2 through behavior

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    bbc47933552e4c90846c80e731b06ddfIf you had to work with Yii2 sure there was a situation when it was necessary to keep communication “many-to-many”.

    When it became clear that the network has no behaviors to work with this type of connection, then the correct code was written at the event «after save» and with a warning “works well also” went to the repository.

    Personally, I am not satisfied with such a disposition of events. I decided to write something very magical behavior, which is so lacking in the official assembly Yii2.

    Installation

    Install through the Composer:

    php composer.phar require --prefer-dist voskobovich/yii2-many-many-behavior "*"
    

    Or add into composer.json of your project to the section «require»:

    "voskobovich/yii2-many-many-behavior": "*"
    

    Execute:

    ~$ php composer.phar update
    

    Source: yii2-many-many-behavior.

    How to use?

    Connecting the behavior in the desired model ActiveRecord:

    public function behaviors()
    {
        return [
            [
                'class' => \voskobovich\behaviors\ManyToManyBehavior::className(),
                'users_list' => 'users',
                'tasks_list' => [
                    'tasks',
                    'get' => function($value) {
                        return JSON::decode($value);
                    },
                    'set' => function($value) {
                        return JSON::encode($value);
                    },
                 ]
            ],
        ];
    }
    

    This example describes two connections:

    1. Communication «users» will receive and store the primary keys in the properties of the model «users_list».
    2. Communication «tasks» respectively «tasks_list». At the same time, for a given connection are indicated handlers «set» and «get» which process data before saving the communication and output in the field.

    Please note that the properties of «users_list» and «tasks_list» will appear in the model automatically!

    Next, add fields in the form of creating/edit:

    <?= $form->field($model, 'users_list')
          ->dropDownList(ArrayHelper::map(User::find()->all(), 's_id', 'name'), ['multiple' => true]) ?>
    

    and allow them to update through mass assignment by adding validation rules:

    public function rules()
    {
        return [
            [['users_list', 'tasks_list'], 'safe']
        ];
    }
    

    or you can work with new properties directly:

    $model->users_list = [2,5,6,7];
    

    After these manipulations links will be updated automatically.

    From the properties of «users_list» and «tasks_list» you can also get an array of primary keys stored on communication models.

    print_r($model->users_list);
    

    Returns an array of primary keys stored on the communication «users».

    It is worth saying that the formation of a list of primary keys happens only at the moment of the call of reading properties.

    Thank you for your attention!

    This text is a translation of the article “Сохранение “много ко многим” в Yii2 через поведение” by rafic published on habrahabr.ru.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • 84% of the WordPress site can be hacked: What’s Next?

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    f3ca345cc7ed3cf2bb0e3396a0596528

    If you often read IT-news, you probably already tired of the horror stories about another vulnerability that was found in the popular OS / database / CMS / coffee maker. Therefore, this post is not about the vulnerability and about monitoring how people react to it.

    But first – a few words about “the villain of the peace”. Critical vulnerabilities in popular WordPress blogging engine was found in September by the Finnish specialists from companies with funny name Klikki Oy. Using this hole, the hacker can lead as a comment to the blog a special code that will be executed in the browser of the site administrator when reading comments. Attack allows you to secretly take over the site and do unpleasant things under the admin access.

    Here’s how easy it looks like in practice. Go to the blog by WordPress and enter a bad comment:

    8758dfb3bad2ce0e7a14dd14cdd535db

    Next we see a specially crafted comment allows to bypass checks and conduct XSS-attack:

    b76d8a02ea439497f939a01fd973e02a

    After capturing admin permissions an attacker can run their code on the server that is hosting the attacked blog, that is, can develop an attack on a broad front. Now is the time to remember that just recently 800,000 credit cards were stolen by a bank trojan which was distributed across WordPress sites.

    This vulnerability applies to all versions of WordPress 3.0 and higher. Problem can be solved upgrade engine to version 4, where no such problem.

    And now about the actual reaction. Finnish security experts discovered a vulnerability reported it to the vendor on September 26. At the time of this writing, that is, two months later after finding renewed no more than 16% of users of WordPress (see diagram on the title picture post). What Finnish experts concluded that all the other 84%, that is tens of millions of users of this engine in the world, stay potential victims.

    In fact, the victims will certainly be less because there is a small additional condition for the operation – need the opportunity to comment on posts or pages (default is available without authorization). However, we are interested in here is the lifetime of vulnerability, and in this case it is possible to observe in real time – to monitor the statistics update WordPress here. Although you probably already understand the meaning of these figures: don’t lock the barn door after the horse is stolen.

    We also follow the intruders attempt to exploit this vulnerability “in the wild”. To do this, use a network attack detection based applications PT Application Firewall. The mechanism of intrusion detection based on the analysis of anomalies in this case worked well, and we did not have to add the signature. In other words, PT AF elicited this “0 day” from the very beginning:

    7cb201b9b1a2dd366483e30842c7c00f

    At the moment, the vulnerability exploitation attempts is already found. They can not be called mass – but if you have an older WordPress, should still be updated.

    This text is a translation of article “84% сайтов на WordPress могут быть взломаны: что дальше?” by ptsecurity published on habrahabr.ru.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • Little-known functions in WordPress

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    Has it ever happened that during parsing code-party plugin or theme you found quite useful standard function, which did not know before? At such moments, any developer feels a sense of worthlessness, remembering he reinvented the wheel in previous projects.

    In order to reduce the amount of frustration, I decided to describe a few little-known but very useful features:

    make_clickable
    Find in the text links and make them clickable.
    Example:

    $string = "This is a long text that contains some links like https://www.wordpress.org and https://www.wordpress.com .";
    echo make_clickable( $string ); 
    

    popuplinks
    Adds  target='_ blank' rel='external' to all the links in the text.
    Example:

    $string = "This is a long text that contains some links like <a href='https://www.wordpress.org'>https://www.wordpress.org</a> and <a href='https://www.wordpress.com'>https://www.wordpress.com</a> .";
    echo popuplinks( $string ); 
    

    wp_list_pluck
    Takes out certain fields from the collection.
    Example:

    $posts = get_posts();
    $ids = wp_list_pluck( $posts, 'ID' ); // [1, 2, 3, ...]
    

    antispambot
    Converts email addresses to symbols HTML for protection from spambots.
    Example:

    $email = 'ex*****@em***.com';
    echo '<a href="mailto:' . antispambot( $email ) . '">' . antispambot( $email ) . '</a>';
    

    checked / selected
    Adds an attribute checked (selected) if the first argument is equal to the second.
    Example:

    <input type="checkbox" name="remember" value="1" <?php checked( $remember ) ?> />
    <select name="options">
        <option value="1" <?php selected( $options, 1 ); ?>>1</option>
        <option value="2" <?php selected( $options, 2 ); ?>>2</option>
        <option value="3" <?php selected( $options, 3 ); ?>>3</option>
    </select>
    

    human_time_diff
    Represents the difference in time in human-readable form.
    Example:

    $published = get_the_time( 'U' );
    echo human_time_diff( $published ); // 2 days
    

    wp_send_json_success / wp_send_json_error
    Displays data in a JSON format for Ajax requests.
    Example:

    if( $success ) {
        $result = array(
            'message'	=> 'Saved',
            'ID'		=> 1
        );
        wp_send_json_success( $result ); // { "success": true, "data": { "message": "Saved", "ID": 1 } }
    }
    else {
        wp_send_json_error(); // { "success": false }
    }
    

    wp_remote_get / wp_remote_post
    Receives data from a third-party web resource.
    Example:

    $response = wp_remote_get( "https://api.twitter.com/1.1/search/tweets.json?q=%23WordPress", array( 'timeout' => 10 ) );
    $tweets = wp_remote_retrieve_body( $response );
    

    wp_is_mobile
    Specifies the user’s device.
    Example:

    if ( wp_is_mobile() ) {
        get_footer( 'mobile' );
    }
    else {
        get_footer();
    }
    

    wp_oembed_get
    Converts a link to a media resource in the code of the player.
    Example:

    $youtube_url = 'https://www.youtube.com/watch?v=Lcvh0DgytH8';
    $embed_code = wp_oembed_get( $youtube_url, array( 'width' => 800 ) );
    

    wp_tempnam
    Creates a temporary file with a unique name.
    Example:

    wp_tempnam( 'cache.log', get_temp_dir() );
    

    zeroise
    Complements the number with zeros to the specified length.
    Example:

    $tickets_count = 8;
    echo zeroise( $tickets_count, 3 ); // 008
    

    capital_P_dangit
    Corrects common errors in brand name WordPress.
    Example:

    $string = "I Love WordPress";
    echo capital_P_dangit( $string ); // I Love WordPress
    

    get_num_queries
    Shows the total number of SQL-queries to the database page.
    Example:

    <!-- Number of queries: <?php echo get_num_queries(); ?> -->
    

    wp_text_diff
    Finds the differences in the text and displays them in a convenient form for comparison.
    Example:

    $left_string = 'This is the original string';
    $right_string = 'This is the revised string';
    echo wp_text_diff( $left_string, $right_string );
    

    submit_button
    Generates code for the button.
    Example:

    <?php submit_button( __( 'Save Changes' ) ); ?>
    

    enjoy 🙂

    This text is a translation of article “Малоизвестные функции в WordPress” by Pingbull published on habrahabr.ru.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • Yii 2.0. Release

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    After three years of intensive development and nearly 10,000 commits more than 300 authors published a stable version of PHP framework Yii 2.0! Thank you for your support and patience!

    As you may already know, Yii 2.0 has been rewritten from scratch. This decision was made because we wanted to get a good PHP framework that preserves the simplicity and extensibility of Yii and, at the same time, will use the latest technologies and capabilities to become even better. Today we are pleased to announce that the goal has been reached.

    A few useful links about Yii and Yii 2.0:

    Next we look at the most interesting features of the new version. If you are in a hurry to try the framework in the case, start by reading the section of the manual Getting Started.

    The most interesting

    Adherence to the standards and use the latest technologies

    Yii 2.0 uses namespaces and traits PHP, standards PSR, Composer and Bower. All this makes the job more enjoyable with the framework. Third-party libraries are now much easier to use.

    Reliable basis

    As 1.1, Yii 2.0 supported object properties through getters and setters, configurations, events and behaviors. The new code is more efficient and expressive. For example, you can handle the event as follows:

    $response = new yii\web\Response;
    $response->on('beforeSend', function ($event) {
        // handle the event "beforeSend"
    });
    

    In Yii 2.0 are realized dependency injection container and service locator. When used properly, they make applications more flexible and testable.

    Development tools

    Yii 2.0 includes several tools that make it easier for developers life.

    Yii debugger allows to study the details of your application. It can also be used for profiling and find bottlenecks.

    As of version 1.1, Yii 2.0 have significantly saving time code generator Gii. It perfectly expands that lets you create your generators. Gii can work with both the browser and from the console.

    Documentation API Yii 1.1 has received many accolades. Many wanted the same documentation for their projects, so Yii 2.0 included documentation generator. It supports Markdown, which allows you to write more consistently and eloquently.

    Security

    Yii 2.0 helps you write more secure code. In the framework, there are opportunities to prevent SQL injection, XSS attacks, CSRF attacks, forgery cookie etc. Some parts of the code have been checked by security experts Tom Worster and Anthony Ferrara and later rewritten.

    Databases

    Working with databases has never been this easy. Yii 2.0 supports migration, DAO, query builder and Active Record. When compared to 1.1 in version 2.0 improved performance of Active Record, and the syntax to work with this is the same as when using the Query Builder. Below shows the preparation of customer data using the Query Builder and Active Record. In both cases use the chain of method invocation, which resembles SQL.

    use yii\db\Query;
    use app\models\Customer;
    
    $customers = (new Query)->from('customer')
        ->where(['status' => Customer::STATUS_ACTIVE])
        ->orderBy('id')
        ->all();
        
    $customers = Customer::find()
        ->where(['status' => Customer::STATUS_ACTIVE])
        ->orderBy('id')
        ->asArray();
        ->all();
    

    The following code shows a sample of related data through Active Record:

    namespace app\models;
    
    use app\models\Order;
    use yii\db\ActiveRecord;
    
    class Customer extends ActiveRecord
    {
        public static function tableName()
        {
            return 'customer';
        }
        
        // specifies the type of connection one-to-many with model Order
        public function getOrders()
        {
            return $this->hasMany(Order::className(), ['customer_id' => 'id']);
        }
    }
    
    // returns to the client with id equal to 100
    $customer = Customer::findOne(100);
    // returns the client orders
    $orders = $customer->orders;
    

    Below we update the customer record. This uses the binding parameters, which virtually eliminates the possibility of SQL injection. The database saves only changed data.

    $customer = Customer::findOne(100);
    $customer->address = '123 Anderson St';
    $customer->save();  // execute SQL: UPDATE `customer` SET `address`='123 Anderson St' WHERE `id`=100
    

    Yii 2.0 supports multiple databases. Besides the commonly used relational database support added Cubrid, ElasticSearch and Sphinx. Also supported and NoSQL store such as Redis and MongoDB. To access all the databases, both through the Query Builder, and through Active Record uses the same API, making it easy to migrate from one repository to another use. If you use Active Record can build links between data from different databases (for example, between MySQL and Redis).

    For applications with large databases and high performance requirements in Yii 2.0 supports replication of DB and division read/write.

    RESTful API

    Yii allows you to get a working and compatible with the latest protocols RESTful API to write only a few lines of code. The example below shows the creation of RESTful API for user data.

    First, create a controller app\controllers\UserController and specify app\models\User as a data model:

    namespace app\controllers;
    
    use yii\rest\ActiveController;
    
    class UserController extends ActiveController
    {
        public $modelClass = 'app\models\User';
    }
    
    

    Next, change the configuration of the component urlManager so to use beautiful URL:

    'urlManager' => [
        'enablePrettyUrl' => true,
        'enableStrictParsing' => true,
        'showScriptName' => false,
        'rules' => [
            ['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
        ],
    ]
    

    Done! API, which was just created, supports:

    • GET /users: a list of all users paged;
    • HEAD /users: titles with information about the list of users;
    • POST /users: create a new user;
    • GET /users/123: user information with id = 123;
    • HEAD /users/123: titles with information about the user with id = 123;
    • PATCH /users/123 and PUT /users/123: updates the information of user with id = 123;
    • DELETE /users/123: removes the user with id = 123;
    • OPTIONS /users: returns the HTTP verbs supported for /users;
    • OPTIONS /users/123: returns the HTTP verbs supported for /users/123.

    API, you can try using curl:

    $ curl -i -H "Accept:application/json" "https://localhost/users"
    
    HTTP/1.1 200 OK
    Date: Sun, 02 Mar 2014 05:31:43 GMT
    Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
    X-Powered-By: PHP/5.4.20
    X-Pagination-Total-Count: 1000
    X-Pagination-Page-Count: 50
    X-Pagination-Current-Page: 1
    X-Pagination-Per-Page: 20
    Link: <https://localhost/users?page=1>; rel=self, 
          <https://localhost/users?page=2>; rel=next, 
          <https://localhost/users?page=50>; rel=last
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=UTF-8
    
    [
        {
            "id": 1,
            ...
        },
        {
            "id": 2,
            ...
        },
        ...
    ]
    

    Caching

    As in version 1.1 Yii 2.0 cache as excellent support on the server side (fragments, requests) and client side (HTTP). There are many drivers for storage, including APC, Memcache, files, databases, etc.

    Forms

    In Yii 1.1, you can quickly create an HTML form that supports both client and server validation. In the second version make it even easier. The following example shows how to create the login form.

    First created model LoginForm, which is collected from the form data. The model specifies the validation rules which are automatically used to generate the necessary validation on the client JavaScript.

    use yii\base\Model;
    
    class LoginForm extends Model
    {
        public $username;
        public $password;
    
        /**
         * @return array the validation rules.
         */
        public function rules()
        {
            return [
                // username and password are both required
                [['username', 'password'], 'required'],
                // password is validated by validatePassword()
                ['password', 'validatePassword'],
            ];
        }
    
        /**
         * Validates the password.
         * This method serves as the inline validation for password.
         */
        public function validatePassword()
        {
            $user = User::findByUsername($this->username);
            if (!$user || !$user->validatePassword($this->password)) {
                $this->addError('password', 'Incorrect username or password.');
            }
        }
    }
    

    Next, create a view:

    use yii\helpers\Html;
    use yii\widgets\ActiveForm;
    
    <?php $form = ActiveForm::begin() ?>
        <?= $form->field($model, 'username') ?>
        <?= $form->field($model, 'password')->passwordInput() ?>
        <?= Html::submitButton('Login') ?>
    <? ActiveForm::end() ?>
    

    Authentication and authorization

    As of version 1.1, Yii 2.0 has built-in authentication and user authorization. Supports input, output, cookie-based authentication and token, access control filter and access control based on roles (RBAC).

    It is also possible entry via external services for OpenID, OAuth1 and OAuth2. There are ready-made support for popular services such as Facebook, GitHub, Google, Twitter, Vkontakte and Yandex.

    Widgets

    For building interactive user interfaces in the framework included a lot of ready-made elements called widgets. There is support for widgets Bootstrap and jQuery UI. It also offers such frequently used items like pagination, grid, list, etc. All they are doing web application development is really fast and pleasant process. For example, using the following code, you can get a fully working element jQuery UI to select a date in Russian:

    use yii\jui\DatePicker;
    
    echo DatePicker::widget([
        'name' => 'date',
        'language' => 'ru',
        'dateFormat' => 'yyyy-MM-dd',
    ]);
    
    

    Helpers

    To simplify common tasks in the framework, there are helpers. For example, in Html helper methods are assembled to create different HTML tags and Url helper allows you to create different URL:

    use yii\helpers\Html;
    use yii\helpers\Url;
    
    // creates a list of checkboxes with countries
    echo Html::checkboxList('country', 'USA', $countries);
    
    // displays the URL "/index?r=site/index&src=ref1#name"
    echo Url::to(['site/index', 'src' => 'ref1', '#' => 'name']);

    Internationalization

    Since the framework is used around the world, we have taken care of a good support for internationalization. Supports message translation and translation of view, based on the locale multiple forms and data formatting standard ICU. For example:

    // translation of message formatted date
    echo \Yii::t('app', 'Today is {0, date}', time());
    
    // translation of message with multiple forms
    echo \Yii::t('app', 'There {n, plural, =0{are no cats} =1{is one cat} other{are # cats}}!', ['n' => 0]);
    
    

    Templating

    By default, Yii 2.0 uses as a template language PHP, but also supports Twig and Smarty through special extensions. Ability to create and expand their support for other template.

    Testing

    Yii 2.0 officially supports integration with Codeception and Faker. The framework included a decision to fixture through the migration, which makes the work with the data for testing more convenient.

    Application templates

    In order to make the development more rapidly in release includes two templates of applications, each of which is a fully functional web application. Basic template is recommended to use as a basis for relatively simple small web projects, such as portals and personal websites. Advanced template is more suitable for large-scale applications divided into a plurality of servers developed by a large team.

    Extensions

    Despite the fact that Yii 2.0 provides many useful features, it implemented a system extension that makes it even more powerful. An extension is distributed separately packages specifically designed for use in applications Yii. Many opportunities already handed in Yii extensions, such as sending mail and Bootstrap. The site has a large Yii user library, currently numbering nearly 1,700 extensions. Packagist.org can be found on more than 1,300 packages for Yii.

    Getting Started

    To get started, enter the following commands:

    # set composer-asset-plugin globally. This should be done once.
    php composer.phar global require "fxp/composer-asset-plugin:1.0.0-beta2"
    
    # set the basic application template
    php composer.phar create-project yiisoft/yii2-app-basic basic 2.0.0
    

    The above commands will work if you have already installed Composer. If it is not, it is necessary to install it.

    It is worth noting that during the installation process Composer may require a login and password from GitHub to generate a token that allows to overcome the limitations on the number of requests to the API.

    After executing the above command, you can start working with the web application available at URL https://localhost/basic/web/index.php.

    Update

    If you are upgrading from a previous version of Yii 2.0 (alpha, beta or RC), follow the instructions.

    Upgrading from version 1.1 without rewriting application code is impossible since Yii 2.0 has been completely rewritten and syntax changes a lot. Nevertheless, many ideas are stored, so that work with 2.0, 1.1 knowledge, will be easier. Big changes compared to version 1.1 are described in detail in the documentation.

    Documentation

    For Yii 2.0 is available complete guide and documentation for API. Manual translated into many languages. Translations will be available a little later. By Yii 2.0 is already out one book and write more. One of the books will be written by well-known technical writer Larry Ullman, who helps us with a complete guide. Alexander Makarov coordinates and edits the cookbook Yii 2.0, similar to that adopted by the warm cookbook Yii 1.1.

    Thanks

    Thanks to all who participated and participates in the development Yii.
    Your support is invaluable!

    This text is a translation of article “Yii 2.0. Релиз” by SamDark published on habrahabr.ru.

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

  • Accelerate WordPress

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.

    WordPress in the standard setting is quite slow. By default, the engine does not use some features of modern web for significant acceleration. There are a whole bunch of plugins to optimize WordPress. Let’s put things in order and undergo a major optimization to accelerate WordPress.

    Before we begin, let’s see what shows raw installing WordPress on Pagespeed:

    Result 76 out of 100 is pretty low. Let’s see how you can increase this figure.

    Server part

    Ngnix

    If you’re not already using Nginx, it’s time to move on it. Simple and powerful solution. Configuration for supporting permalinks and static caching:

    server {
            server_name wp.com;
            root /var/www/wp; # way to WP
            index index.php;
    
            location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                    access_log off;
                    log_not_found off;
                    expires max; # statistics caching 
            }
    
            location / {
                    try_files $uri $uri/ /index.php?$args; # permalinks
            }
    
            location ~ \.php$ {
                    fastcgi_pass unix:/var/run/php5-fpm.sock;
                    fastcgi_index index.php;
                    include fastcgi_params;
            }
    }
    

    PHP cach

    If you do not have any special reasons why you can not install APC, turn it necessarily. Checks for APC (in response to obtain a list of settings APC):

    php -i | grep apc

    In PHP versions after 5.5 has a built-in module opCache, so it will not have to put the APC.

    Tuning Mysql

    WordPress uses InnoDB, which means we can significantly increase productivity of MySQL, adjust the number of parameters (file my.cnf) under our hardware:

    The size of the buffer InnoDB is better to put in half the available RAM:

    innodb_buffer_pool_size = 256M
    

    Do not forget to include the caching of MySQL:

    query_cache_size = 32M
    query_cache_limit = 1M
    

    Caching

    This is the most important point. Caching can give a significant acceleration of the site and save server resources. For clarity, we will use ab from Apache. Verify the standard install WordPress without caching. The request is sent through a local network, so the delay is nothing but itself does not create a WordPress:

    ab -c 10 -n 500 https://wordpress/

    Obtain the average time of about 50ms on request:

    Total transferred:      4183000 bytes
    HTML transferred:       4074500 bytes
    Requests per second:    17.62 [#/sec] (mean)
    Time per request:       567.421 [ms] (mean)
    Time per request:       56.742 [ms] (mean, across all concurrent requests)
    Transfer rate:          143.98 [Kbytes/sec] received
    

    Chrome shows the average wait for the response at 150 ms (the server is in the Netherlands):

    WP Super Cache

    This plugin allows you to enable caching literally in one action. Besides the default settings, it contains a large number of settings for tuning the cache. Download plugin, activate it in the control panel and turn on the cache

    With the included WP Super Cache obtain a reduction of the average time per query 25 times (!):

    Total transferred:      4293500 bytes
    HTML transferred:       4146500 bytes
    Requests per second:    499.01 [#/sec] (mean)
    Time per request:       20.040 [ms] (mean)
    Time per request:       2.004 [ms] (mean, across all concurrent requests)
    Transfer rate:          4184.61 [Kbytes/sec] received
    

    Average absorption waiting for reply in Chrome decreased by 3 times:

    As an alternative to server-WP Super Cache can use Varnish. It reduces the time to process a request for nearly an order of magnitude, but the solution is less flexible (well suited for blogs without elements of dynamics).

    Styles, scripts and images

    Minification and Compression

    Minification CSS / JS can save 10 … 15% of their size. To enable a module minification statics WP Minify. Download it, activate, and the module starts. Gzip will reduce the size of the text files into several times. In Nginx activated as follows:

    server {
    ...
    gzip on;
    gzip_disable "msie6";
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
    ...
    }
    

    Optimizing images

    Pictures can be very large part of the overall page size. Lossless compression of images can save 30 … 40% of their size. This module is able to do EWWW Image Optimizer. For it to work you will need to install imagemagick and library gd:

    apt-get install imagemagick php5-gd
    

    Good practice and experience

    • It is best to choose a VPS hosting for WordPress. Shared hosting on many of the above can be done. In addition, VPS now cheap enough
    • Check the topics using Pagespeed before use
    • Clean trash
    • Delete old revisions of posts
    • Remove spam comments
    • Unplug trackbacks to moments when everything becomes very slow
    • Share RSS via feedburner

    As a result

    We’ve got a raw install WordPress to disperse about 100 times on the page generation time (we included Varnish) and increase the rate at Pagespeed from 76 to 93:

    This text is a translation of article “Ускоряем WordPress” by golotyuk published on habrahabr.ru 

    Forums and blogs without spam

    CleanTalk is a SaaS spam protection service for Web-sites. CleanTalk uses protection methods which are invisible for site visitors. Connecting to the service eliminates needs for CAPTCHA, questions and answers and other methods of protection, complicating the exchange of information on the site.