aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-external-packages
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-external-packages')
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/command/command.rs8
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/helper_set.rs143
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs38
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs26
4 files changed, 77 insertions, 138 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/command/command.rs b/crates/shirabe-external-packages/src/symfony/console/command/command.rs
index 2d94ad2..59aa915 100644
--- a/crates/shirabe-external-packages/src/symfony/console/command/command.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/command/command.rs
@@ -822,9 +822,11 @@ impl Command for CommandData {
Some(helper_set) => helper_set,
};
- // TODO(review): HelperSet::get() returns `Rc<RefCell<dyn HelperInterface>>`, but
- // Command::getHelper() is typed `mixed` (PhpMixed) here and PhpMixed cannot hold a
- // helper instance. The helper return modelling needs a dedicated type (Phase C).
+ // TODO(plugin): PHP's Command::getHelper($name) looks a helper up by string via
+ // HelperSet::get($name). The HelperSet is now a closed set exposing only typed getters
+ // (get_formatter/get_question/...), so a string-keyed lookup no longer exists. Callers
+ // should use the typed getters on the HelperSet directly; restoring name-based lookup is
+ // deferred until the plugin API (which is the only source of dynamically named helpers).
let _ = helper_set;
todo!()
}
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/helper_set.rs b/crates/shirabe-external-packages/src/symfony/console/helper/helper_set.rs
index e73a53e..d72b627 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/helper_set.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/helper_set.rs
@@ -1,117 +1,76 @@
//! ref: composer/vendor/symfony/console/Helper/HelperSet.php
-use crate::symfony::console::command::command::Command;
-use crate::symfony::console::exception::invalid_argument_exception::InvalidArgumentException;
+use crate::symfony::console::helper::debug_formatter_helper::DebugFormatterHelper;
+use crate::symfony::console::helper::formatter_helper::FormatterHelper;
use crate::symfony::console::helper::helper_interface::HelperInterface;
-use indexmap::IndexMap;
+use crate::symfony::console::helper::process_helper::ProcessHelper;
+use crate::symfony::console::helper::question_helper::QuestionHelper;
use std::cell::RefCell;
use std::rc::Rc;
/// HelperSet represents a set of helpers to be used with a command.
///
-/// @implements \IteratorAggregate<string, Helper>
-#[derive(Debug, Default, Clone)]
+/// Symfony lets arbitrary helpers be registered by name, but Composer only ever uses the four
+/// helpers `Application::getDefaultHelperSet()` installs. This port closes the set to exactly those
+/// four, instantiates them in the argument-less constructor, and exposes them through typed getters
+/// instead of Symfony's string-keyed `get()`/`has()`/`set()`.
+///
+/// TODO(plugin): a plugin-defined custom command may register extra helpers dynamically via
+/// `getApplication()->getHelperSet()`. Restoring that path (a `set()` equivalent plus name-based
+/// lookup) is deferred until the plugin API is implemented.
+#[derive(Debug)]
pub struct HelperSet {
- helpers: IndexMap<String, Rc<RefCell<dyn HelperInterface>>>,
- command: Option<Rc<RefCell<dyn Command>>>,
+ formatter_helper: Rc<RefCell<FormatterHelper>>,
+ debug_formatter_helper: Rc<RefCell<DebugFormatterHelper>>,
+ process_helper: Rc<RefCell<ProcessHelper>>,
+ question_helper: Rc<RefCell<QuestionHelper>>,
}
impl HelperSet {
- /// @param Helper[] $helpers An array of helper
- pub fn new(
- this: &Rc<RefCell<HelperSet>>,
- helpers: IndexMap<HelperSetKey, Rc<RefCell<dyn HelperInterface>>>,
- ) {
- for (alias, helper) in helpers {
- let alias = match alias {
- HelperSetKey::Int(_) => None,
- HelperSetKey::String(alias) => Some(alias),
- };
- Self::set(this, helper, alias.as_deref());
- }
- }
+ /// Builds the fixed set of helpers and wires each one's back-reference to the owning set,
+ /// mirroring the `$helper->setHelperSet($this)` call PHP's `HelperSet::set()` performs.
+ pub fn new() -> Rc<RefCell<HelperSet>> {
+ let formatter_helper = Rc::new(RefCell::new(FormatterHelper::default()));
+ let debug_formatter_helper = Rc::new(RefCell::new(DebugFormatterHelper::default()));
+ let process_helper = Rc::new(RefCell::new(ProcessHelper::default()));
+ let question_helper = Rc::new(RefCell::new(QuestionHelper::default()));
- pub fn set(
- this: &Rc<RefCell<HelperSet>>,
- helper: Rc<RefCell<dyn HelperInterface>>,
- alias: Option<&str>,
- ) {
- let name = helper.borrow().get_name();
- this.borrow_mut().helpers.insert(name, helper.clone());
- if let Some(alias) = alias {
- this.borrow_mut()
- .helpers
- .insert(alias.to_string(), helper.clone());
- }
+ let this = Rc::new(RefCell::new(HelperSet {
+ formatter_helper: formatter_helper.clone(),
+ debug_formatter_helper: debug_formatter_helper.clone(),
+ process_helper: process_helper.clone(),
+ question_helper: question_helper.clone(),
+ }));
- helper.borrow_mut().set_helper_set(Some(this.clone()));
- }
+ formatter_helper
+ .borrow_mut()
+ .set_helper_set(Some(this.clone()));
+ debug_formatter_helper
+ .borrow_mut()
+ .set_helper_set(Some(this.clone()));
+ process_helper
+ .borrow_mut()
+ .set_helper_set(Some(this.clone()));
+ question_helper
+ .borrow_mut()
+ .set_helper_set(Some(this.clone()));
- /// Returns true if the helper if defined.
- pub fn has(&self, name: &str) -> bool {
- self.helpers.contains_key(name)
+ this
}
- /// Gets a helper value.
- ///
- /// @throws InvalidArgumentException if the helper is not defined
- pub fn get(
- &self,
- name: &str,
- ) -> Result<Rc<RefCell<dyn HelperInterface>>, InvalidArgumentException> {
- if !self.has(name) {
- return Err(InvalidArgumentException(
- shirabe_php_shim::InvalidArgumentException {
- message: format!(
- "The helper \"{}\" is not defined.",
- shirabe_php_shim::PhpMixed::String(name.to_string()),
- ),
- code: 0,
- },
- ));
- }
-
- Ok(self.helpers[name].clone())
+ pub fn get_formatter(&self) -> Rc<RefCell<FormatterHelper>> {
+ self.formatter_helper.clone()
}
- /// @deprecated since Symfony 5.4
- pub fn set_command(&mut self, command: Option<Rc<RefCell<dyn Command>>>) {
- shirabe_php_shim::trigger_deprecation(
- "symfony/console",
- "5.4",
- "Method \"%s()\" is deprecated.",
- "HelperSet::setCommand",
- );
-
- self.command = command;
+ pub fn get_debug_formatter(&self) -> Rc<RefCell<DebugFormatterHelper>> {
+ self.debug_formatter_helper.clone()
}
- /// Gets the command associated with this helper set.
- ///
- /// @deprecated since Symfony 5.4
- pub fn get_command(&self) -> Option<Rc<RefCell<dyn Command>>> {
- shirabe_php_shim::trigger_deprecation(
- "symfony/console",
- "5.4",
- "Method \"%s()\" is deprecated.",
- "HelperSet::getCommand",
- );
-
- self.command.clone()
+ pub fn get_process(&self) -> Rc<RefCell<ProcessHelper>> {
+ self.process_helper.clone()
}
- /// @return \Traversable<string, Helper>
- pub fn get_iterator(
- &self,
- ) -> impl Iterator<Item = (&String, &Rc<RefCell<dyn HelperInterface>>)> {
- self.helpers.iter()
+ pub fn get_question(&self) -> Rc<RefCell<QuestionHelper>> {
+ self.question_helper.clone()
}
}
-
-/// PHP array keys are either integers or strings; the HelperSet constructor
-/// distinguishes them via `\is_int($alias)`.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum HelperSetKey {
- Int(i64),
- String(String),
-}
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs
index e62b9ac..f141bee 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/process_helper.rs
@@ -57,12 +57,11 @@ impl ProcessHelper {
let output: Rc<RefCell<dyn OutputInterface>> =
todo!("$output instanceof ConsoleOutputInterface redirect to error output");
- let formatter: Rc<RefCell<dyn HelperInterface>> = self
+ let formatter: Rc<RefCell<DebugFormatterHelper>> = self
.get_helper_set()
.unwrap()
.borrow()
- .get("debug_formatter")
- .unwrap();
+ .get_debug_formatter();
// Normalize $cmd: a single Process becomes a one-element array.
let mut cmd = match cmd {
@@ -234,12 +233,11 @@ impl ProcessHelper {
let output: Rc<RefCell<dyn OutputInterface>> =
todo!("$output instanceof ConsoleOutputInterface redirect to error output");
- let formatter: Rc<RefCell<dyn HelperInterface>> = self
+ let formatter: Rc<RefCell<DebugFormatterHelper>> = self
.get_helper_set()
.unwrap()
.borrow()
- .get("debug_formatter")
- .unwrap();
+ .get_debug_formatter();
let object_hash = shirabe_php_shim::spl_object_hash_process(process);
@@ -268,46 +266,30 @@ impl ProcessHelper {
shirabe_php_shim::str_replace("<", "\\<", str)
}
- /// PHP fetches `debug_formatter` from the HelperSet as a `HelperInterface` and
- /// dynamically dispatches `start`/`stop`/`progress`, which are concrete
- /// `DebugFormatterHelper` methods not present on the interface. Resolving the
- /// dynamic helper handle back to the concrete `DebugFormatterHelper` is a
- /// downcast that requires a Phase C decision (e.g. an `as_any` on
- /// `HelperInterface`); deferred here.
- fn debug_formatter(
- _formatter: &Rc<RefCell<dyn HelperInterface>>,
- ) -> Rc<RefCell<DebugFormatterHelper>> {
- todo!("downcast HelperInterface handle to DebugFormatterHelper (Phase C)")
- }
-
fn formatter_start(
- formatter: &Rc<RefCell<dyn HelperInterface>>,
+ formatter: &Rc<RefCell<DebugFormatterHelper>>,
id: &str,
message: &str,
) -> String {
- Self::debug_formatter(formatter)
- .borrow_mut()
- .start(id, message, "RUN")
+ formatter.borrow_mut().start(id, message, "RUN")
}
fn formatter_stop(
- formatter: &Rc<RefCell<dyn HelperInterface>>,
+ formatter: &Rc<RefCell<DebugFormatterHelper>>,
id: &str,
message: &str,
successful: bool,
) -> String {
- Self::debug_formatter(formatter)
- .borrow_mut()
- .stop(id, message, successful, "RES")
+ formatter.borrow_mut().stop(id, message, successful, "RES")
}
fn formatter_progress(
- formatter: &Rc<RefCell<dyn HelperInterface>>,
+ formatter: &Rc<RefCell<DebugFormatterHelper>>,
id: &str,
buffer: &str,
error: bool,
) -> String {
- Self::debug_formatter(formatter)
+ formatter
.borrow_mut()
.progress(id, buffer, error, "OUT", "ERR")
}
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
index db9c094..f2c2a00 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
@@ -5,6 +5,7 @@ use crate::symfony::console::exception::missing_input_exception::MissingInputExc
use crate::symfony::console::exception::runtime_exception::RuntimeException;
use crate::symfony::console::formatter::output_formatter::OutputFormatter;
use crate::symfony::console::formatter::output_formatter_style::OutputFormatterStyle;
+use crate::symfony::console::helper::formatter_helper::FormatBlockMessages;
use crate::symfony::console::helper::helper::Helper;
use crate::symfony::console::helper::helper_interface::HelperInterface;
use crate::symfony::console::helper::helper_set::HelperSet;
@@ -316,22 +317,17 @@ impl QuestionHelper {
output: Rc<RefCell<dyn OutputInterface>>,
error: &shirabe_php_shim::Exception,
) {
- let message;
- if let Some(helper_set) = self.get_helper_set() {
- if helper_set.borrow().has("formatter") {
- // PHP: `$this->getHelperSet()->get('formatter')->formatBlock(...)`.
- // HelperSet::get yields `dyn HelperInterface`, which does not have
- // `AsAny` as a supertrait, so it cannot be downcast to
- // FormatterHelper. Resolved once HelperInterface gains AsAny (see
- // report).
- let _formatter = helper_set.borrow().get("formatter").unwrap();
- todo!("downcast dyn HelperInterface to FormatterHelper for format_block");
- } else {
- message = format!("<error>{}</error>", error.message);
- }
+ let message = if let Some(helper_set) = self.get_helper_set() {
+ let formatter = helper_set.borrow().get_formatter();
+ let message = formatter.borrow().format_block(
+ FormatBlockMessages::String(error.message.clone()),
+ "error",
+ false,
+ );
+ message
} else {
- message = format!("<error>{}</error>", error.message);
- }
+ format!("<error>{}</error>", error.message)
+ };
output
.borrow()