• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

extphprs / ext-php-rs / 20424568890

22 Dec 2025 07:07AM UTC coverage: 35.997% (-0.06%) from 36.059%
20424568890

Pull #628

github

web-flow
Merge 1573d74a8 into 4ef666b34
Pull Request #628: fix(stubs): Constants' values are now properly transferred

19 of 66 new or added lines in 5 files covered. (28.79%)

3 existing lines in 1 file now uncovered.

1694 of 4706 relevant lines covered (36.0%)

12.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/constant.rs
1
//! Types and traits for registering constants in PHP.
2

3
use cfg_if::cfg_if;
4
use std::ffi::CString;
5
use std::fmt::Debug;
6

7
use super::flags::GlobalConstantFlags;
8
use crate::error::Result;
9
use crate::ffi::{
10
    zend_register_bool_constant, zend_register_double_constant, zend_register_long_constant,
11
    zend_register_string_constant,
12
};
13

14
/// Implemented on types which can be registered as a constant in PHP.
15
pub trait IntoConst: Debug {
16
    /// Returns the PHP stub representation of this constant value.
17
    ///
18
    /// This is used when generating PHP stub files for IDE autocompletion.
19
    /// The returned string should be a valid PHP literal (e.g., `"hello"`,
20
    /// `42`, `true`).
21
    fn stub_value(&self) -> String;
22

23
    /// Registers a global module constant in PHP, with the value as the content
24
    /// of self. This function _must_ be called in the module startup
25
    /// function, which is called after the module is initialized. The
26
    /// second parameter of the startup function will be the module number.
27
    /// By default, the case-insensitive and persistent flags are set when
28
    /// registering the constant.
29
    ///
30
    /// Returns a result containing nothing if the constant was successfully
31
    /// registered.
32
    ///
33
    /// # Parameters
34
    ///
35
    /// * `name` - The name of the constant.
36
    /// * `module_number` - The module number that we are registering the
37
    ///   constant under.
38
    ///
39
    /// # Errors
40
    ///
41
    /// Returns an error if the constant could not be registered.
42
    ///
43
    /// # Examples
44
    ///
45
    /// ```no_run
46
    /// use ext_php_rs::constant::IntoConst;
47
    ///
48
    /// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
49
    ///     5.register_constant("MY_CONST_NAME", module_number); // MY_CONST_NAME == 5
50
    ///     "Hello, world!".register_constant("STRING_CONSTANT", module_number); // STRING_CONSTANT == "Hello, world!"
51
    ///     0
52
    /// }
53
    /// ```
54
    fn register_constant(&self, name: &str, module_number: i32) -> Result<()> {
×
55
        self.register_constant_flags(name, module_number, GlobalConstantFlags::Persistent)
×
56
    }
57

58
    /// Registers a global module constant in PHP, with the value as the content
59
    /// of self. This function _must_ be called in the module startup
60
    /// function, which is called after the module is initialized. The
61
    /// second parameter of the startup function will be the module number.
62
    /// This function allows you to pass any extra flags in if you require.
63
    /// Note that the case-sensitive and persistent flags *are not* set when you
64
    /// use this function, you must set these yourself.
65
    ///
66
    /// Returns a result containing nothing if the constant was successfully
67
    /// registered.
68
    ///
69
    /// # Parameters
70
    ///
71
    /// * `name` - The name of the constant.
72
    /// * `module_number` - The module number that we are registering the
73
    ///   constant under.
74
    /// * `flags` - Flags to register the constant with.
75
    ///
76
    /// # Errors
77
    ///
78
    /// Returns an error if the constant flags could not be registered.
79
    ///
80
    /// # Examples
81
    ///
82
    /// ```no_run
83
    /// use ext_php_rs::{constant::IntoConst, flags::GlobalConstantFlags};
84
    ///
85
    /// pub extern "C" fn startup_function(_type: i32, module_number: i32) -> i32 {
86
    ///     42.register_constant_flags("MY_CONST_NAME", module_number, GlobalConstantFlags::Persistent | GlobalConstantFlags::Deprecated);
87
    ///     0
88
    /// }
89
    /// ```
90
    fn register_constant_flags(
91
        &self,
92
        name: &str,
93
        module_number: i32,
94
        flags: GlobalConstantFlags,
95
    ) -> Result<()>;
96
}
97

98
impl IntoConst for String {
NEW
99
    fn stub_value(&self) -> String {
×
NEW
100
        self.as_str().stub_value()
×
101
    }
102

UNCOV
103
    fn register_constant_flags(
×
104
        &self,
105
        name: &str,
106
        module_number: i32,
107
        flags: GlobalConstantFlags,
108
    ) -> Result<()> {
109
        self.as_str()
×
110
            .register_constant_flags(name, module_number, flags)
×
111
    }
112
}
113

114
impl IntoConst for &str {
NEW
115
    fn stub_value(&self) -> String {
×
116
        // Escape special characters for PHP string literal
NEW
117
        let escaped = self
×
118
            .replace('\\', "\\\\")
119
            .replace('\'', "\\'")
120
            .replace('\n', "\\n")
121
            .replace('\r', "\\r")
122
            .replace('\t', "\\t");
NEW
123
        format!("'{escaped}'")
×
124
    }
125

UNCOV
126
    fn register_constant_flags(
×
127
        &self,
128
        name: &str,
129
        module_number: i32,
130
        flags: GlobalConstantFlags,
131
    ) -> Result<()> {
132
        unsafe {
133
            cfg_if! {
134
                if #[cfg(php85)] {
135
                    let _ = zend_register_string_constant(
136
                        CString::new(name)?.as_ptr(),
137
                        name.len() as _,
138
                        CString::new(*self)?.as_ptr(),
139
                        flags.bits().try_into()?,
140
                        module_number,
141
                    );
142
                } else {
143
                    zend_register_string_constant(
×
144
                        CString::new(name)?.as_ptr(),
×
145
                        name.len() as _,
×
146
                        CString::new(*self)?.as_ptr(),
×
147
                        flags.bits().try_into()?,
×
148
                        module_number,
×
149
                    );
150
                }
151
            }
152
        };
153
        Ok(())
×
154
    }
155
}
156

157
impl IntoConst for bool {
NEW
158
    fn stub_value(&self) -> String {
×
NEW
159
        if *self { "true" } else { "false" }.to_string()
×
160
    }
161

UNCOV
162
    fn register_constant_flags(
×
163
        &self,
164
        name: &str,
165
        module_number: i32,
166
        flags: GlobalConstantFlags,
167
    ) -> Result<()> {
168
        unsafe {
169
            cfg_if! {
170
                if #[cfg(php85)] {
171
                    let _ = zend_register_bool_constant(
172
                        CString::new(name)?.as_ptr(),
173
                        name.len() as _,
174
                        *self,
175
                        flags.bits().try_into()?,
176
                        module_number,
177
                    );
178
                } else {
179
                    zend_register_bool_constant(
×
180
                        CString::new(name)?.as_ptr(),
×
181
                        name.len() as _,
×
182
                        *self,
×
183
                        flags.bits().try_into()?,
×
184
                        module_number,
×
185
                    );
186
                }
187
            }
188
        };
189
        Ok(())
×
190
    }
191
}
192

193
/// Implements the `IntoConst` trait for a given number type using a given
194
/// function.
195
macro_rules! into_const_num {
196
    ($type: ty, $fn: expr) => {
197
        impl IntoConst for $type {
NEW
198
            fn stub_value(&self) -> String {
×
NEW
199
                self.to_string()
×
200
            }
201

202
            fn register_constant_flags(
×
203
                &self,
×
204
                name: &str,
×
205
                module_number: i32,
×
206
                flags: GlobalConstantFlags,
×
207
            ) -> Result<()> {
×
208
                unsafe {
209
                    cfg_if! {
210
                        if #[cfg(php85)] {
211
                            let _ = $fn(
212
                                CString::new(name)?.as_ptr(),
213
                                name.len() as _,
214
                                (*self).into(),
215
                                flags.bits().try_into()?,
216
                                module_number,
217
                            );
218
                        } else {
219
                            $fn(
220
                                CString::new(name)?.as_ptr(),
×
221
                                name.len() as _,
×
222
                                (*self).into(),
×
223
                                flags.bits().try_into()?,
×
224
                                module_number,
×
225
                            );
226
                        }
227
                    }
228
                };
229
                Ok(())
×
230
            }
231
        }
232
    };
233
}
234

235
into_const_num!(i8, zend_register_long_constant);
236
into_const_num!(i16, zend_register_long_constant);
237
into_const_num!(i32, zend_register_long_constant);
238
into_const_num!(i64, zend_register_long_constant);
239
into_const_num!(f32, zend_register_double_constant);
240
into_const_num!(f64, zend_register_double_constant);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc