Completed
Push — master ( 7b2295...f28f63 )
by Askupa
02:10
created

Manager::get_instance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Amarkal\Shortcode;
4
5
class Manager
6
{
7
    /**
8
     * @var Singleton The reference to *Singleton* instance of this class
9
     */
10
    private static $instance;
11
    
12
    private $shortcodes = array();
13
    
14
    /**
15
     * Returns the *Singleton* instance of this class.
16
     *
17
     * @return Singleton The *Singleton* instance.
18
     */
19
    public static function get_instance()
20
    {
21
        if( null === static::$instance ) 
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $instance to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
22
        {
23
            static::$instance = new static();
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $instance to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
Documentation Bug introduced by
It seems like new static() of type this<Amarkal\Shortcode\Manager> is incompatible with the declared type object<Amarkal\Shortcode\Singleton> of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
24
        }
25
        return static::$instance;
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $instance to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
Bug Compatibility introduced by
The expression static::$instance; of type Amarkal\Shortcode\Manage...kal\Shortcode\Singleton adds the type Amarkal\Shortcode\Manager to the return on line 25 which is incompatible with the return type documented by Amarkal\Shortcode\Manager::get_instance of type Amarkal\Shortcode\Singleton.
Loading history...
26
    }
27
    
28
    public function register_shortcode( $args )
29
    {
30
        $this->validate_args($args);
31
        if($this->shortcode_exists($args['id']))
32
        {
33
            throw new \RuntimeException("A shortcode with id '{$args['id']}' has already been registered");
34
        }
35
        $this->shortcodes[$args['id']] = array_merge($this->default_args(), $args);
36
    }
37
    
38
    public function print_json_object($plugin_array)
39
    {
40
        
41
        return $plugin_array;
42
    }
43
    
44
    public function enqueue_script($plugins_array)
45
    {
46
        // Printing the JSON object ensures that it will be available whenever 
47
        // the visual editor is present.
48
        echo "<script id='amarkal-shortcode-json' type='application/json'>{$this->prepare_json_object()}</script>";
49
        
50
        // This script must be included after the JSON object, since it refers
51
        // to it, and so the JSON must be readily available.
52
        $plugins_array['amarkal_shortcode'] = \Amarkal\Core\Utility::path_to_url(__DIR__.'/tinymce.plugin.js');
53
        return $plugins_array;
54
    }
55
    
56
    /**
57
     * Create a JSON object that will be printed in the admin section
58
     * to be used by the TinyMCE plugin code.
59
     */
60
    private function prepare_json_object()
61
    {
62
        $json = array();
63
        foreach($this->shortcodes as $id => $shortcode)
64
        {
65
            $popup = new Popup($shortcode['fields']);
66
            $json[$id] = $shortcode;
67
            $json[$id]['html'] = $popup->render();
68
        }
69
        return json_encode($json);
70
    }
71
    
72
    /**
73
     * Default shortcode arguments
74
     */
75
    private function default_args()
76
    {
77
        return array(
78
            'id'                => null,
79
            'title'             => '',
80
            'template'          => null,
81
            'cmd'               => '',
82
            'width'             => 550,
83
            'height'            => 450,
84
            'fields'            => array(),
85
            'show_placeholder'  => true,
86
            'placeholder_class' => null
87
        );
88
    }
89
    
90
    /**
91
     * Check if a shortcode with the given ID has already been registered
92
     */
93
    private function shortcode_exists( $id )
94
    {
95
        return array_key_exists($id, $this->shortcodes);
96
    }
97
    
98
    /**
99
     * Validate that the provided arguments have the required arguments as
100
     * specified in self::required_args()
101
     */
102
    private function validate_args( $args )
103
    {
104
        foreach($this->required_args() as $arg)
105
        {
106
            if(!array_key_exists($arg, $args))
107
            {
108
                throw new \RuntimeException("Missing required argument '$arg'");
109
            }
110
        }
111
    }
112
    
113
    /**
114
     * A list of required arguments
115
     */
116
    private function required_args()
117
    {
118
        return array('id','template','fields');
119
    }
120
121
    /**
122
     * Private constructor to prevent instantiation
123
     */
124
    private function __construct() 
125
    {
126
        \add_filter('mce_external_plugins',array($this,'enqueue_script'));
127
    }
128
}