Kristof Coomans
function twitter_fetch_user_timeline($id) {
$account = twitter_account_load($id);
$since = db_query("...", array(':screen_name' => $account->screen_name))
->fetchField();
$twitter = twitter_connect($account);
$params = $since ? array('since_id' => $since) : array();
$statuses = $twitter->user_timeline($id, $params);
foreach ($statuses as $status) {
twitter_status_save($status);
}
if (count($statuses) > 0) {
twitter_account_save($statuses[0]->user);
}
}
function twitter_connect($account) {
$auth = $account->get_auth();
return new Twitter(
variable_get('twitter_consumer_key'),
variable_get('twitter_consumer_secret'),
$auth['oauth_token'],
$auth['oauth_token_secret']
);
}
Is this code easily testable and maintainable?
SOLID: 5 basic principles of object oriented programming and design
(Robert C. Martin)
Definition in YAML inside your module named example:
example.services.yml
Simplest form:
services:
asset.css.optimizer:
class: Drupal\Core\Asset\CssOptimizer
Equivalent to:
new \Drupal\Core\Asset\CssOptimizer();
services:
database:
...
config.storage.active:
class: Drupal\Core\Config\DatabaseStorage
arguments: ['@database', config]
config.storage.snapshot:
class: Drupal\Core\Config\DatabaseStorage
arguments: ['@database', config_snapshot]
Equivalent to:
$database = ... $activeConfigStorage = new \Drupal\Core\Config\DatabaseStorage( $database, 'config' ); $snapshotConfigStorage = new \Drupal\Core\Config\DatabaseStorage( $database, 'config_snapshot' );
theme.manager:
class: Drupal\Core\Theme\ThemeManager
arguments: ...
calls:
- [setThemeRegistry, ['@theme.registry']]
theme.registry:
class: Drupal\Core\Theme\Registry
arguments: ...
calls:
- [setThemeManager, ['@theme.manager']]
Equivalent to:
$themeManager = new \Drupal\Core\Theme\ThemeManager(...); $themeRegistry = new \Drupal\Core\Theme\Registry(...); $themeRegistry->setThemeManager($themeManager); $themeManager->setThemeRegistry($themeRegistry);
Code smell!
Creation by a static factory method
services:
database:
class: Drupal\Core\Database\Connection
factory_class: Drupal\Core\Database\Database
factory_method: getConnection
arguments: [default]
Equivalent to:
$database = \Drupal\Core\Database\Database::getConnection('default');
OR by a factory service
services:
cache_factory:
...
cache.menu:
class: Drupal\Core\Cache\CacheBackendInterface
factory_method: get
factory_service: cache_factory
arguments: [menu]
Equivalent to:
$cacheFactory = ...;
$menuCache = $cacheFactory::get('menu');
$container = \Drupal::getContainer();
$languageManager = $container->get('language_manager');
However, avoid using \Drupal::getContainer(), use dependency injection instead!
Implement a factory method interface!
/**
* Provides a 'Language switcher' block.
* ...
*/
class LanguageBlock
extends BlockBase
implements ContainerFactoryPluginInterface
{
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
LanguageManagerInterface $language_manager,
PathMatcherInterface $path_matcher
) {
...
}
public static function create(
ContainerInterface $container,
array $configuration,
$plugin_id,
$plugin_definition
) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('language_manager'),
$container->get('path.matcher')
);
}
}
class UserController extends ControllerBase {
public function __construct(
DateFormatter $date_formatter,
UserStorageInterface $user_storage,
UserDataInterface $user_data
) {
$this->dateFormatter = $date_formatter;
$this->userStorage = $user_storage;
$this->userData = $user_data;
}
public static function create(
ContainerInterface $container
) {
return new static(
$container->get('date.formatter'),
$container->get('entity.manager')->getStorage('user'),
$container->get('user.data')
);
}
}
Faster to write it like in the old days?
$database = \Drupal\Core\Database\Database::getConnection('default');
services:
database:
class: Drupal\Core\Database\Connection
factory_class: Drupal\Core\Database\Database
factory_method: getConnection
arguments: [default]
Remember:
Technique to improve your code, by applying far stricter coding standards, among which:
How to check? PHP CodeSniffer ruleset
List all upcoming events of the Drupal User Group Belgium announced at their Meetup page in a Block on a Drupal 8 website, by using their API.
Bonus: add caching on the API requests.