Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
79.55% |
35 / 44 |
|
46.15% |
6 / 13 |
CRAP | |
0.00% |
0 / 1 |
| GadgetResourceLoaderModule | |
79.55% |
35 / 44 |
|
46.15% |
6 / 13 |
36.20 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getGadget | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
3.33 | |||
| getPages | |
93.75% |
15 / 16 |
|
0.00% |
0 / 1 |
9.02 | |||
| getScript | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
| getRequireKey | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| validateScriptFile | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| isPackaged | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getDependencies | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getType | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| getMessages | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getSkins | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| requiresES6 | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getGroup | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace MediaWiki\Extension\Gadgets; |
| 4 | |
| 5 | use InvalidArgumentException; |
| 6 | use MediaWiki\MainConfigNames; |
| 7 | use MediaWiki\MediaWikiServices; |
| 8 | use MediaWiki\ResourceLoader as RL; |
| 9 | |
| 10 | /** |
| 11 | * Class representing a list of resources for one gadget, basically a wrapper |
| 12 | * around the Gadget class. |
| 13 | */ |
| 14 | class GadgetResourceLoaderModule extends RL\WikiModule { |
| 15 | /** |
| 16 | * @var string |
| 17 | */ |
| 18 | private $id; |
| 19 | |
| 20 | /** |
| 21 | * @var Gadget |
| 22 | */ |
| 23 | private $gadget; |
| 24 | |
| 25 | public function __construct( array $options ) { |
| 26 | $this->id = $options['id']; |
| 27 | } |
| 28 | |
| 29 | /** |
| 30 | * @return Gadget instance this module is about |
| 31 | */ |
| 32 | private function getGadget() { |
| 33 | if ( !$this->gadget ) { |
| 34 | /** @var GadgetRepo $repo */ |
| 35 | $repo = MediaWikiServices::getInstance()->getService( 'GadgetsRepo' ); |
| 36 | try { |
| 37 | $this->gadget = $repo->getGadget( $this->id ); |
| 38 | } catch ( InvalidArgumentException ) { |
| 39 | // Fallback to a placeholder object... |
| 40 | $this->gadget = Gadget::newEmptyGadget( $this->id ); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | return $this->gadget; |
| 45 | } |
| 46 | |
| 47 | /** |
| 48 | * @param RL\Context $context |
| 49 | * @return array |
| 50 | */ |
| 51 | protected function getPages( RL\Context $context ) { |
| 52 | // In theory we could support these separately, but |
| 53 | // * gadget definitions assume both |
| 54 | // * it doesn't make sense to load half a gadget |
| 55 | // * it's poor UX to have some gadgets work and some not |
| 56 | // * historically this extension is only used when |
| 57 | // a community permits both. |
| 58 | $config = $this->getConfig(); |
| 59 | if ( !$config->get( MainConfigNames::UseSiteJs ) || !$config->get( MainConfigNames::UseSiteCss ) ) { |
| 60 | return []; |
| 61 | } |
| 62 | |
| 63 | $gadget = $this->getGadget(); |
| 64 | $pages = []; |
| 65 | |
| 66 | foreach ( $gadget->getStyles() as $style ) { |
| 67 | $pages[$style] = [ 'type' => 'style' ]; |
| 68 | } |
| 69 | |
| 70 | if ( $gadget->supportsResourceLoader() ) { |
| 71 | foreach ( $gadget->getScripts() as $script ) { |
| 72 | $pages[$script] = [ 'type' => 'script' ]; |
| 73 | } |
| 74 | if ( $gadget->isPackaged() ) { |
| 75 | foreach ( $gadget->getVues() as $vue ) { |
| 76 | $pages[$vue] = [ 'type' => 'script-vue' ]; |
| 77 | } |
| 78 | foreach ( $gadget->getJSONs() as $json ) { |
| 79 | $pages[$json] = [ 'type' => 'data' ]; |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | return $pages; |
| 85 | } |
| 86 | |
| 87 | /** |
| 88 | * @inheritDoc |
| 89 | */ |
| 90 | public function getScript( RL\Context $context ) { |
| 91 | $module = parent::getScript( $context ); |
| 92 | |
| 93 | if ( $this->isPackaged() && $this->gadget->getCodexIcons() ) { |
| 94 | // Add codex icons to the gadget module |
| 95 | $module['files']['icons.json'] = [ |
| 96 | 'type' => 'data', |
| 97 | 'content' => RL\CodexModule::getIcons( $context, $this->getConfig(), $this->gadget->getCodexIcons() ), |
| 98 | ]; |
| 99 | } |
| 100 | return $module; |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * @param string $titleText |
| 105 | * @return string |
| 106 | */ |
| 107 | public function getRequireKey( $titleText ): string { |
| 108 | /** @var GadgetRepo $repo */ |
| 109 | $repo = MediaWikiServices::getInstance()->getService( 'GadgetsRepo' ); |
| 110 | return $repo->titleWithoutPrefix( $titleText, $this->id ); |
| 111 | } |
| 112 | |
| 113 | /** |
| 114 | * @param string $fileName |
| 115 | * @param string $contents |
| 116 | * @return string |
| 117 | */ |
| 118 | protected function validateScriptFile( $fileName, $contents ) { |
| 119 | // Temporary solution to support gadgets in ES6 by disabling validation |
| 120 | // for them and putting them in a separate resource group to avoid a syntax error in them |
| 121 | // from corrupting core/extension-loaded scripts or other non-ES6 gadgets. |
| 122 | if ( $this->requiresES6() ) { |
| 123 | return $contents; |
| 124 | } |
| 125 | return parent::validateScriptFile( $fileName, $contents ); |
| 126 | } |
| 127 | |
| 128 | /** |
| 129 | * Returns whether this gadget is packaged. |
| 130 | */ |
| 131 | public function isPackaged(): bool { |
| 132 | return $this->getGadget()->isPackaged(); |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * @param RL\Context|null $context |
| 137 | * @return string[] Names of resources this module depends on |
| 138 | */ |
| 139 | public function getDependencies( ?RL\Context $context = null ) { |
| 140 | return $this->getGadget()->getDependencies(); |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * @return string RL\Module::LOAD_STYLES or RL\Module::LOAD_GENERAL |
| 145 | */ |
| 146 | public function getType() { |
| 147 | return $this->getGadget()->getType() === 'styles' |
| 148 | ? RL\Module::LOAD_STYLES |
| 149 | : RL\Module::LOAD_GENERAL; |
| 150 | } |
| 151 | |
| 152 | /** @inheritDoc */ |
| 153 | public function getMessages() { |
| 154 | return $this->getGadget()->getMessages(); |
| 155 | } |
| 156 | |
| 157 | /** @inheritDoc */ |
| 158 | public function getSkins(): ?array { |
| 159 | return $this->getGadget()->getRequiredSkins() ?: null; |
| 160 | } |
| 161 | |
| 162 | /** @inheritDoc */ |
| 163 | public function requiresES6(): bool { |
| 164 | return $this->getGadget()->requiresES6(); |
| 165 | } |
| 166 | |
| 167 | /** @inheritDoc */ |
| 168 | public function getGroup() { |
| 169 | return $this->requiresES6() ? 'es6-gadget' : self::GROUP_SITE; |
| 170 | } |
| 171 | } |