diff --git a/.env.example b/.env.example index 8369ce365..7a6559e5a 100644 --- a/.env.example +++ b/.env.example @@ -42,6 +42,19 @@ ADMIN_LTI_NAME="UDOIT 3 Admin" USE_DEVELOPMENT_AUTH="no" VERSION_NUMBER="3.5.0" +# Define which accessibility checker to use +# Available options: "phpally", "equalaccess_local", "equalaccess_lambda" +ACCESSIBILITY_CHECKER="equalaccess_lambda" + +# NOTE: When using a lambda function with equal access, +# you need to define the following in a separate .env.local: +# EQUALACCESS_AWS_ACCESS_KEY_ID= +# EQUALACCESS_AWS_SECRET_ACCESS_KEY= +# EQUALACCESS_AWS_REGION= +# EQUALACCESS_AWS_SERVICE= +# EQUALACCESS_AWS_HOST=abcdefghi.execute-api.us-east-1.amazonaws.com +# EQUALACCESS_CANONICAL_URI=endpoint/generate-accessibility-report + ###> symfony/messenger ### MESSENGER_TRANSPORT_DSN=doctrine://default diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df80c8c67..8025c0494 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: branches: - main - 'stable/*' + - 'equal-access' env: REGISTRY: ghcr.io diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e2ff0c27..85d9c6306 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ Please update this file as you open PRs and make changes to the codebase. Thank you! ## [Unreleased](https://github.com/ucfopen/UDOIT/tree/dev) +## [4.0] -- In Progress + +- Upgraded the React version from 16.14.0 to 18.3.1, as well as updating a lot of the React code from class-based components to functional. Changes seen in [#984](https://github.com/ucfopen/UDOIT/pull/984) (Thank you [@mbusch3](https://github.com/mbusch3) and [@nizolnier](https://github.com/nizolnier)). +- Updated UDOIT's PHP version from 8.2 to 8.4 to avoid issues pulling the latest composer image, as well as work with a php version that has active support. (Thank you, [@dmols](https://github.com/dmols) and [@panbed](https://github.com/panbed)) +- Integrated IBM Equal Access scanner to act as the new default UDOIT scanner (replacing PHPAlly) while still allowing developers to choose between the two. Changes seen in [#982](https://github.com/ucfopen/UDOIT/pull/982) (Thank you, [@panbed](https://github.com/panbed) and [@evannaderi](https://github.com/evannaderi)) + ## [3.5.0](https://github.com/ucfopen/UDOIT/compare/3.4.0...3.5.0) - 2024-11-12 ### General diff --git a/Dockerfile b/Dockerfile index f77fd0b95..a9ced79af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.2-fpm +FROM php:8.4.2-fpm ARG ENVIRONMENT_TYPE #Install dependencies and php extensions diff --git a/assets/js/Components/AboutModal.js b/assets/js/Components/AboutModal.js index 478aefcf0..27b45377f 100644 --- a/assets/js/Components/AboutModal.js +++ b/assets/js/Components/AboutModal.js @@ -6,38 +6,30 @@ import { CloseButton } from '@instructure/ui-buttons' import AboutPage from './AboutPage' -class AboutModal extends React.Component { - constructor(props) { - super(props) - } - - render() { - return ( - - - - - {this.props.t('label.about')} - - - this.props.handleModal(null)} - /> - - - - - - - - ) - } -} - -export default AboutModal \ No newline at end of file +export default function AboutModal({ t, settings, handleModal }) { + return ( + + + + + {t('label.about')} + + + handleModal(null)} + /> + + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/AboutPage.js b/assets/js/Components/AboutPage.js index 85474ac5d..7802d07e1 100644 --- a/assets/js/Components/AboutPage.js +++ b/assets/js/Components/AboutPage.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState, useEffect } from 'react' import { Heading } from '@instructure/ui-heading' import { View } from '@instructure/ui-view' import { Text } from '@instructure/ui-text' @@ -10,133 +10,127 @@ import * as Html from '../Services/Html' import ReactHtmlParser from 'react-html-parser' import Classes from '../../css/theme-overrides.css' -class AboutPage extends React.Component { +export default function AboutPage({ t, settings }) { + const [expandDetails, setExpandDetails] = useState(false) + const [issues, setIssues] = useState({"error": [], "suggestion": []}) - constructor(props) { - super(props) - - this.state = { - expandDetails: false - } - - this.handleDetailsToggle = this.handleDetailsToggle.bind(this) + const handleDetailsToggle = () => { + setExpandDetails(!expandDetails) } - handleDetailsToggle() { - this.setState({ expandDetails: !this.state.expandDetails }) - } + useEffect(() => { + const suggestionTypes = (settings.suggestionRuleIds != null) ? settings.suggestionRuleIds : '' - render() { - const suggestionTypes = (this.props.settings.suggestionRuleIds != null) ? this.props.settings.suggestionRuleIds : '' - this.issues = { + let currentIssues = { "error": [], "suggestion": [] } issueRuleIds.forEach(issue => { if (suggestionTypes.includes(issue)) { - this.issues.suggestion.push(issue) + currentIssues.suggestion.push(issue) } else { - this.issues.error.push(issue) + currentIssues.error.push(issue) } }) - return ( - - - + setIssues(currentIssues) + }, []) + + return ( + + + + + + {ReactHtmlParser(t('about.description'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + + {t('about.disclaimer_title')} + + {ReactHtmlParser(t('about.disclaimer'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + + + + {ReactHtmlParser(t('about.video_embed'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + {ReactHtmlParser(t('about.video_link'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + - - {ReactHtmlParser(this.props.t('about.description'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - + {t('about.resources')} - - {this.props.t('about.disclaimer_title')} - - {ReactHtmlParser(this.props.t('about.disclaimer'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - + + + {ReactHtmlParser(t('about.user_guide_link'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + - - + + + - {ReactHtmlParser(this.props.t('about.video_embed'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} + {t('about.policies')} - - {ReactHtmlParser(this.props.t('about.video_link'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} + + {ReactHtmlParser(t('about.youtube_terms'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + {ReactHtmlParser(t('about.google_privacy'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + + + - - - {this.props.t('about.resources')} - - - - {ReactHtmlParser(this.props.t('about.user_guide_link'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} + {Object.keys(issues).map((issueType) => { + const type = issues[issueType] + return ( + + + + {('error' === issueType) ? : }  + {t(`label.plural.${issueType}`)} +
+ {type.map((rule) => { + let showExample = false + if (!t(`rule.example.${rule}`).includes('rule.example')) { + showExample = true + } + return ( + + {t(`rule.label.${rule}`)} + } + > + + {ReactHtmlParser(t(`rule.desc.${rule}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + { + (showExample) && + {ReactHtmlParser(t(`rule.example.${rule}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + } + + + ) + })}
-
- - - - {this.props.t('about.policies')} - - - {ReactHtmlParser(this.props.t('about.youtube_terms'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - - - {ReactHtmlParser(this.props.t('about.google_privacy'), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - - - - - - - - {Object.keys(this.issues).map((issueType) => { - const type = this.issues[issueType] - return ( - - - - {('error' === issueType) ? : }  - {this.props.t(`label.plural.${issueType}`)} -
-
- {type.map((rule) => { - if (!this.props.t(`rule.example.${rule}`).includes('rule.example')) { - var showExample = true - } - return ( - - {this.props.t(`rule.label.${rule}`)} - } - > - - {ReactHtmlParser(this.props.t(`rule.desc.${rule}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - { - (showExample) && - {ReactHtmlParser(this.props.t(`rule.example.${rule}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - } - - - ) - })} -
- ) - })} -
-
- - {this.props.t('label.version')} {this.props.settings.versionNumber} - + ) + })} +
- ) - } -} - -export default AboutPage + + {t('label.version')} {settings.versionNumber} + +
+ ) +} \ No newline at end of file diff --git a/assets/js/Components/App.js b/assets/js/Components/App.js index b73b593bd..cae4bd27e 100644 --- a/assets/js/Components/App.js +++ b/assets/js/Components/App.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState, useCallback, useEffect } from 'react' import WelcomePage from './WelcomePage' import Header from './Header' import SummaryPage from './SummaryPage' @@ -11,266 +11,245 @@ import MessageTray from './MessageTray' import FilesPage from './FilesPage' import SummaryBar from './SummaryBar' -class App extends React.Component { - constructor(props) { - super(props) - - this.initialReport = props.report - this.appFilters = {} - this.settings = props.settings - this.reportHistory = [] - this.messages = props.messages - this.newReportInterval = 5000 - - this.state = { - report: this.initialReport, - navigation: 'welcome', - modal: null, - syncComplete: false, - hasNewReport: false, - } - - this.handleNavigation = this.handleNavigation.bind(this) - this.handleModal = this.handleModal.bind(this) - this.handleAppFilters = this.handleAppFilters.bind(this) - this.clearMessages = this.clearMessages.bind(this) - this.addMessage = this.addMessage.bind(this) - this.t = this.t.bind(this) - this.handleIssueSave = this.handleIssueSave.bind(this) - this.handleFileSave = this.handleFileSave.bind(this) - this.handleCourseRescan = this.handleCourseRescan.bind(this) - this.handleFullCourseRescan = this.handleFullCourseRescan.bind(this) - this.handleNewReport = this.handleNewReport.bind(this) - this.resizeFrame = this.resizeFrame.bind(this) - } - - render() { - return ( - -
- - {(('welcome' !== this.state.navigation) && ('summary' !== this.state.navigation)) && - +export default function App(initialData) { + + // The initialData object that is passed to the App will generally contain: + // { + // messages: [], + // report: { ... The report from the most recent scan ... }, + // settings: { ... From src/Controller/DashboardController.php => getSettings() ... }, + // } + + const [messages, setMessages] = useState(initialData.messages || []) + const [report, setReport] = useState(initialData.report || null) + const [settings, setSettings] = useState(initialData.settings || null) + + // The reportHistory and newReportInterval variables are not used in the current codebase + // const [reportHistory, setReportHistory] = useState([]) + // const [newReportInterval, setNewReportInterval] = useState(5000) + + const [appFilters, setAppFilters] = useState({}) + const [navigation, setNavigation] = useState('welcome') + const [modal, setModal] = useState(null) + const [syncComplete, setSyncComplete] = useState(false) + const [hasNewReport, setHasNewReport] = useState(false) + const [disableReview, setDisableReview] = useState(false) + + // `t` is used for text/translation. It will return the translated string if it exists + // in the settings.labels object. + const t = useCallback((key) => { + return (settings.labels[key]) ? settings.labels[key] : key + }, [settings.labels]) + + const scanCourse = useCallback(() => { + let api = new Api(settings) + return api.scanCourse(settings.course.id) + }, [settings]) + + const fullRescan = useCallback(() => { + let api = new Api(settings) + return api.fullRescan(settings.course.id) + }, [settings]) + + const handleNewReport = (data) => { + let newReport = report + let newHasNewReport = hasNewReport + let newDisableReview = disableReview + if (data.messages) { + data.messages.forEach((msg) => { + if (msg.visible) { + addMessage(msg) } - - - -
- {('welcome' === this.state.navigation) && - - } - {('summary' === this.state.navigation) && - - } - {('content' === this.state.navigation) && - - } - {('files' === this.state.navigation) && - - } - {('reports' === this.state.navigation) && - - } -
- - {('about' === this.state.modal) && - + if ('msg.no_report_created' === msg.message) { + addMessage(msg) + newReport = null + newDisableReview = true } - - ) - } - - componentDidMount() { - if (this.settings.user && Array.isArray(this.settings.user.roles)) { - if (this.settings.user.roles.includes('ROLE_ADVANCED_USER')) { - if (this.initialReport) { - this.setState({report: this.initialReport, navigation: 'summary'}) + if ("msg.sync.course_inactive" === msg.message) { + newDisableReview = true } - } + }) } - - this.scanCourse() - .then((response) => response.json()) - .then(this.handleNewReport) - - // update iframe height on resize - window.addEventListener("resize", this.resizeFrame); - - this.resizeFrame(); + if (data.data && data.data.id) { + newReport = data.data + newHasNewReport = true + } + setSyncComplete(true) + setHasNewReport(newHasNewReport) + setReport(newReport) + setDisableReview(newDisableReview) } - componentWillUnmount() { - window.removeEventListener('resize', this.resizeFrame); + const handleNavigation = (navigation) => { + console.log('handleNavigation to: ', navigation) + setNavigation(navigation) } - t(key) { - return (this.settings.labels[key]) ? this.settings.labels[key] : key + const handleModal = (modal) => { + setModal(modal) } - scanCourse() { - let api = new Api(this.settings) - return api.scanCourse(this.settings.course.id) + const handleAppFilters = (filters) => { + setAppFilters(filters) } - fullRescan() { - let api = new Api(this.settings) - return api.fullRescan(this.settings.course.id) + const addMessage = (msg) => { + setMessages(prevMessages => [...prevMessages, msg]) } - disableReview = () => { - return this.state.syncComplete && !this.state.disableReview + const clearMessages = () => { + setMessages([]) } - handleCourseRescan() { - if (this.state.hasNewReport) { - this.setState({ hasNewReport: false, syncComplete: false }) - this.scanCourse() - .then((response) => response.json()) - .then(this.handleNewReport) - } - this.forceUpdate() - } + const handleIssueSave = (newIssue, newReport) => { + const oldReport = report + const updatedReport = { ...oldReport, ...newReport } - handleFullCourseRescan() { - if (this.state.hasNewReport) { - this.setState({ hasNewReport: false, syncComplete: false }) - this.fullRescan() - .then((response) => response.json()) - .then(this.handleNewReport) + if (updatedReport && Array.isArray(updatedReport.issues)) { + updatedReport.issues = updatedReport.issues.map((issue) => { + if (issue.id === newIssue.id) return newIssue + const oldIssue = oldReport.issues.find((oldReportIssue) => oldReportIssue.id === issue.id) + return oldIssue !== undefined ? { ...oldIssue, ...issue } : issue + }) } - this.forceUpdate() - } - handleNewReport(data) { - let report = this.state.report - let hasNewReport = this.state.hasNewReport - let disableReview = this.state.disableReview - if (data.messages) { - data.messages.forEach((msg) => { - if (msg.visible) { - this.addMessage(msg) - } - if ('msg.no_report_created' === msg.message) { - this.addMessage(msg) - report = null - // no report, do not do any review actions - disableReview = true - } - if ("msg.sync.course_inactive" === msg.message) { - // course scan failed, issues may be outdated - disableReview = true - } - }); - } - if (data.data && data.data.id) { - report = data.data - hasNewReport = true - } - this.setState({ - syncComplete: true, - hasNewReport, - report, - disableReview, - }) + setReport(updatedReport) } - handleNavigation(navigation) { - this.setState({navigation}) - } + const handleFileSave = (newFile, newReport) => { + let updatedReport = { ...report, ...newReport } - handleModal(modal) { - this.setState({modal}) - } + if (updatedReport && updatedReport.files) { + updatedReport.files[newFile.id] = newFile + } - handleAppFilters = (filters) => { - this.appFilters = filters; + setReport(updatedReport) } - addMessage = (msg) => { - this.messages.push(msg) + const handleCourseRescan = () => { + if (hasNewReport) { + setHasNewReport(false) + setSyncComplete(false) + scanCourse() + .then((response) => response.json()) + .then(handleNewReport) + } } - clearMessages = () => { - this.messages = []; + const handleFullCourseRescan = () => { + if (hasNewReport) { + setHasNewReport(false) + setSyncComplete(false) + fullRescan() + .then((response) => response.json()) + .then(handleNewReport) + } } - handleIssueSave(newIssue, newReport) { - const oldReport = this.state.report; + const resizeFrame = useCallback(() => { + let default_height = document.body.scrollHeight + 50 + default_height = default_height > 1000 ? default_height : 1000 - const report = { ...oldReport, ...newReport }; - - if (report && Array.isArray(report.issues)) { - // Combine backend issues with frontend issue state - report.issues = report.issues.map((issue) => { - if (issue.id === newIssue.id) return newIssue; - const oldIssue = oldReport.issues.find((oldReportIssue) => oldReportIssue.id === issue.id); - return oldIssue !== undefined ? { ...oldIssue, ...issue } : issue; - }); + parent.postMessage(JSON.stringify({ + subject: "lti.frameResize", + height: default_height + }), "*") + }, []) + + useEffect(() => { + if (settings.user && Array.isArray(settings.user.roles)) { + if (settings.user.roles.includes('ROLE_ADVANCED_USER')) { + if (initialData.report) { + setReport(initialData.report) + setNavigation('summary') + } + } } - this.setState({ report }); - } + scanCourse() + .then((response) => response.json()) + .then(handleNewReport) - handleFileSave(newFile, newReport) { - let { report } = this.state - report = { ...report, ...newReport } + window.addEventListener("resize", resizeFrame) + resizeFrame() - if (report && report.files) { - report.files[newFile.id] = newFile + return () => { + window.removeEventListener('resize', resizeFrame) } + }, [settings, initialData.report, scanCourse, resizeFrame]) + + return ( + +
+ + {(('welcome' !== navigation) && ('summary' !== navigation)) && + + } - this.setState({ report }) - } + - // resize containing iframe height - resizeFrame(){ - let default_height = document.body.scrollHeight + 50; - default_height = default_height > 1000 ? default_height : 1000; +
+ {('welcome' === navigation) && + + } + {('summary' === navigation) && + + } + {('content' === navigation) && + + } + {('files' === navigation) && + + } + {('reports' === navigation) && + + } +
- // IE 8 & 9 only support string data, so send objects as string - parent.postMessage(JSON.stringify({ - subject: "lti.frameResize", - height: default_height - }), "*"); - } + {('about' === modal) && + + } + + ) } - -export default App diff --git a/assets/js/Components/Constants.js b/assets/js/Components/Constants.js index b1c8e1556..06c880ccc 100644 --- a/assets/js/Components/Constants.js +++ b/assets/js/Components/Constants.js @@ -36,5 +36,8 @@ export const issueRuleIds = [ "VideoEmbedCheck", "VideoProvidesCaptions", "VideosEmbeddedOrLinkedNeedCaptions", - "VideosHaveAutoGeneratedCaptions" + "VideosHaveAutoGeneratedCaptions", + + "img_alt_misuse", + "text_contrast_sufficient", ] diff --git a/assets/js/Components/ContentPage.js b/assets/js/Components/ContentPage.js index 54124c104..3eb5a14e8 100644 --- a/assets/js/Components/ContentPage.js +++ b/assets/js/Components/ContentPage.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Button } from '@instructure/ui-buttons' import { IconCheckLine, IconInfoBorderlessLine, IconNoLine } from '@instructure/ui-icons' import { Billboard } from '@instructure/ui-billboard' @@ -18,136 +18,112 @@ const issueStatusKeys = [ 'resolved' ] -class ContentPage extends React.Component { - constructor(props) { - super(props); - - this.filteredIssues = []; - this.headers = [ - {id: "status", text: '', alignText: "center"}, - { id: "contentTitle", text: this.props.t('label.header.title') }, - { id: "contentType", text: this.props.t('label.header.type') }, - { id: "scanRuleLabel", text: this.props.t('label.issue') }, - {id: "action", text: "", alignText: "end"} - ] - - this.easyRules = issueRuleIds.filter(rule => this.props.settings.easyRuleIds.includes(rule)) - - this.visualRules = issueRuleIds.filter(rule => this.props.settings.visualRuleIds.includes(rule)) - this.auditoryRules = issueRuleIds.filter(rule => this.props.settings.auditoryRuleIds.includes(rule)) - this.cognitiveRules = issueRuleIds.filter(rule => this.props.settings.cognitiveRuleIds.includes(rule)) - this.motorRules = issueRuleIds.filter(rule => this.props.settings.motorRuleIds.includes(rule)) - - this.state = { - activeIssue: null, - trayOpen: false, - modalOpen: false, - activeIndex: -1, - searchTerm: '', - filters: { - contentTypes: [], - issueTypes: [], - issueTitles: [], - issueStatus: ['active'], - issueImpacts: [], - hideUnpublishedContentItems: false, - easyIssues: false, - }, - tableSettings: { - sortBy: 'contentTitle', - ascending: true, - pageNum: 0, - rowsPerPage: (localStorage.getItem('rowsPerPage')) ? localStorage.getItem('rowsPerPage') : '10' - }, - }; - - this.handleTrayToggle = this.handleTrayToggle.bind(this); - this.handleSearchTerm = this.handleSearchTerm.bind(this); - this.handleTableSettings = this.handleTableSettings.bind(this); - this.handleFilter = this.handleFilter.bind(this); - this.handleActiveIssue = this.handleActiveIssue.bind(this); - //this.handleIssueSave = this.handleIssueSave.bind(this) - } - - componentDidMount() { - if (Object.keys(this.props.appFilters).length > 0) { - const newFilters = Object.assign({}, this.resetFilters(), this.props.appFilters); - this.props.handleAppFilters({}); - this.setState({ filters: newFilters }); +export default function ContentPage({ report, setReport, settings, handleIssueSave, appFilters, handleAppFilters, disableReview, t }) { + const filteredIssues = []; + const headers = [ + { id: "status", text: '', alignText: "center" }, + { id: "contentTitle", text: t('label.header.title') }, + { id: "contentType", text: t('label.header.type') }, + { id: "scanRuleLabel", text: t('label.issue') }, + { id: "action", text: "", alignText: "end" } + ] + + const easyRules = issueRuleIds.filter(rule => settings.easyRuleIds.includes(rule)) + const visualRules = issueRuleIds.filter(rule => settings.visualRuleIds.includes(rule)) + const auditoryRules = issueRuleIds.filter(rule => settings.auditoryRuleIds.includes(rule)) + const cognitiveRules = issueRuleIds.filter(rule => settings.cognitiveRuleIds.includes(rule)) + const motorRules = issueRuleIds.filter(rule => settings.motorRuleIds.includes(rule)) + + const [activeIssue, setActiveIssue] = useState(null) + const [trayOpen, setTrayOpen] = useState(false) + const [modalOpen, setModalOpen] = useState(false) + const [activeIndex, setActiveIndex] = useState(-1) + const [searchTerm, setSearchTerm] = useState('') + const [filters, setFilters] = useState({ + contentTypes: [], + issueTypes: [], + issueTitles: [], + issueStatus: ['active'], + issueImpacts: [], + hideUnpublishedContentItems: false, + easyIssues: false, + }) + const [tableSettings, setTableSettings] = useState({ + sortBy: 'contentTitle', + ascending: true, + pageNum: 0, + rowsPerPage: (localStorage.getItem('rowsPerPage')) ? localStorage.getItem('rowsPerPage') : '10' + }) + + useEffect(() => { + if (Object.keys(appFilters).length > 0) { + const newFilters = Object.assign({}, resetFilters(), appFilters); + handleAppFilters({}); + setFilters(newFilters); } - } + }, []) - handleSearchTerm = (e, val) => { - this.setState({searchTerm: val, filteredIssues: [], tableSettings: Object.assign({}, this.state.tableSettings, {pageNum: 0})}); + const handleSearchTerm = (e, val) => { + setSearchTerm(val); + setFilteredIssues([]); + setTableSettings(Object.assign({}, tableSettings, { pageNum: 0 })); } - // Opens the modal with the appropriate form based on the issue passed in - handleReviewClick = (activeIssue) => { - if (!this.props.disableReview) return; - this.setState({ - modalOpen: true, - activeIssue: activeIssue - }) + const handleReviewClick = (activeIssue) => { + if (!disableReview) return; + setModalOpen(true); + setActiveIssue(activeIssue); } - handleCloseButton = () => { - const newReport = { ...this.props.report }; + const handleCloseButton = () => { + const newReport = { ...report }; newReport.issues = newReport.issues.map((issue) => { issue.recentlyResolved = false; issue.recentlyUpdated = false; return issue; }); - - this.setState({ - report: newReport, - modalOpen: false - }); + + setModalOpen(false); + setReport(newReport); } - handleTrayToggle = (e, val) => { - this.setState({trayOpen: !this.state.trayOpen}); + const handleTrayToggle = (e, val) => { + setTrayOpen(!trayOpen); } - handleFilter = (filter) => { - this.setState({ - filters: Object.assign({}, this.state.filters, filter), - tableSettings: { - sortBy: 'scanRuleLabel', - ascending: true, - pageNum: 0, - }, - activeIndex: -1, - }) + const handleFilter = (filter) => { + setFilters(Object.assign({}, filters, filter)); + setTableSettings({ + sortBy: 'scanRuleLabel', + ascending: true, + pageNum: 0, + }); + setActiveIndex(-1); } - handleActiveIssue(newIssue, newIndex) { - this.setState({ - activeIssue: newIssue, - activeIndex: Number(newIndex) - }) + const handleActiveIssue = (newIssue, newIndex = undefined) => { + setActiveIssue(newIssue); + if(newIndex !== undefined) { + setActiveIndex(Number(newIndex)); + } } - handleTableSettings = (setting) => { - this.setState({ - tableSettings: Object.assign({}, this.state.tableSettings, setting) - }); + const handleTableSettings = (setting) => { + setTableSettings(Object.assign({}, tableSettings, setting)); } - getContentById = (contentId) => { - return Object.assign({}, this.props.report.contentItems[contentId]); + const getContentById = (contentId) => { + return Object.assign({}, report.contentItems[contentId]); } - getFilteredContent = () => { - const report = this.props.report; - const filters = Object.assign({}, this.state.filters); - const { sortBy, ascending } = this.state.tableSettings - + const getFilteredContent = () => { let filteredList = []; let issueList = Object.assign({}, report.issues); + const tempFilters = Object.assign({}, filters); // Check for easy issues filter - if(filters.easyIssues && filters.issueTitles.length == 0) { - filters.issueTitles = this.easyRules + if (tempFilters.easyIssues && tempFilters.issueTitles.length == 0) { + tempFilters.issueTitles = easyRules } // Loop through the issues @@ -155,51 +131,51 @@ class ContentPage extends React.Component { let issue = Object.assign({}, value) // Check if we are interested in this issue severity, aka "type" - if (filters.issueTypes.length !== 0 && !filters.issueTypes.includes(issue.type)) { + if (tempFilters.issueTypes.length !== 0 && !tempFilters.issueTypes.includes(issue.type)) { continue; } // Check if we are interested in issues with this rule impact - if (filters.issueImpacts.length !== 0 - && !(filters.issueImpacts.includes('visual') && this.visualRules.includes(issue.scanRuleId)) - && !(filters.issueImpacts.includes('auditory') && this.auditoryRules.includes(issue.scanRuleId)) - && !(filters.issueImpacts.includes('cognitive') && this.cognitiveRules.includes(issue.scanRuleId)) - && !(filters.issueImpacts.includes('motor') && this.motorRules.includes(issue.scanRuleId)) - ) { + if (tempFilters.issueImpacts.length !== 0 + && !(tempFilters.issueImpacts.includes('visual') && visualRules.includes(issue.scanRuleId)) + && !(tempFilters.issueImpacts.includes('auditory') && auditoryRules.includes(issue.scanRuleId)) + && !(tempFilters.issueImpacts.includes('cognitive') && cognitiveRules.includes(issue.scanRuleId)) + && !(tempFilters.issueImpacts.includes('motor') && motorRules.includes(issue.scanRuleId)) + ) { continue; } // Check if we are interested in issues with this rule title - if (filters.issueTitles.length !== 0 && !filters.issueTitles.includes(issue.scanRuleId)) { + if (tempFilters.issueTitles.length !== 0 && !tempFilters.issueTitles.includes(issue.scanRuleId)) { continue; } // Check if we are filtering by issue status if (!issue.recentlyUpdated && !issue.recentlyResolved) { - if (filters.issueStatus.length !== 0 && !filters.issueStatus.includes(issueStatusKeys[issue.status])) { + if (tempFilters.issueStatus.length !== 0 && !tempFilters.issueStatus.includes(issueStatusKeys[issue.status])) { continue; } } // Get information about the content the issue refers to - var contentItem = this.getContentById(issue.contentItemId) + var contentItem = getContentById(issue.contentItemId) // Check if we are showing unpublished content items - if (filters.hideUnpublishedContentItems && !contentItem.status) { + if (tempFilters.hideUnpublishedContentItems && !contentItem.status) { continue; } // Check if we are filtering by content type - if (filters.contentTypes.length !== 0 && !filters.contentTypes.includes(contentItem.contentType)) { + if (tempFilters.contentTypes.length !== 0 && !tempFilters.contentTypes.includes(contentItem.contentType)) { continue; } // Filter by search term if (!issue.keywords) { - issue.keywords = this.createKeywords(issue, contentItem); + issue.keywords = createKeywords(issue, contentItem); } - if (this.state.searchTerm !== '') { - const searchTerms = this.state.searchTerm.toLowerCase().split(' '); + if (searchTerm !== '') { + const searchTerms = searchTerm.toLowerCase().split(' '); if (Array.isArray(searchTerms)) { for (let term of searchTerms) { @@ -213,26 +189,26 @@ class ContentPage extends React.Component { let status if (issue.status == 2) { status = <> - {this.props.t('label.resolved')} + {t('label.resolved')} } else if (issue.status == 1) { status = <> - {this.props.t('label.fixed')} + {t('label.fixed')} } else { if ('error' === issue.type) { status = <> - {this.props.t('label.error')} + {t('label.error')} } else { status = <> - {this.props.t('label.suggestion')} + {t('label.suggestion')} } @@ -243,113 +219,51 @@ class ContentPage extends React.Component { id: issue.id, issue, status, - scanRuleLabel: this.props.t(`rule.label.${issue.scanRuleId}`), - contentType: this.props.t(`content.${contentItem.contentType}`), + scanRuleLabel: t(`rule.label.${issue.scanRuleId}`), + contentType: t(`content.${contentItem.contentType}`), contentTitle: contentItem.title, action: ( ), - onClick: () => this.handleReviewClick(issue), + onClick: () => handleReviewClick(issue), } ); } filteredList.sort((a, b) => { - if (isNaN(a[sortBy]) || isNaN(b[sortBy])) { - return (a[sortBy].toLowerCase() < b[sortBy].toLowerCase()) ? -1 : 1; + if (isNaN(a[tableSettings.sortBy]) || isNaN(b[tableSettings.sortBy])) { + return (a[tableSettings.sortBy].toLowerCase() < b[tableSettings.sortBy].toLowerCase()) ? -1 : 1; } else { - return (Number(a[sortBy]) < Number(b[sortBy])) ? -1 : 1; + return (Number(a[tableSettings.sortBy]) < Number(b[tableSettings.sortBy])) ? -1 : 1; } }); - if (!ascending) { + if (!tableSettings.ascending) { filteredList.reverse(); } return filteredList; } - render() { - const filteredRows = this.getFilteredContent(); - const activeContentItem = (this.state.activeIssue) ? this.getContentById(this.state.activeIssue.contentItemId) : null - - return ( - - this.contentPageForm = node} - handleTableSettings={this.handleTableSettings} - tableSettings={this.state.tableSettings} - /> - - {this.renderFilterTags()} - - - {this.state.trayOpen && } - {this.state.modalOpen && } - - {filteredRows.length === 0 && - } - - ) - } - - createKeywords(issue, contentItem) { + const createKeywords = (issue, contentItem) => { let keywords = []; - keywords.push(this.props.t(`rule.label.${issue.scanRuleId}`).toLowerCase()); - keywords.push(this.props.t(`label.${contentItem.contentType}`).toLowerCase()); + keywords.push(t(`rule.label.${issue.scanRuleId}`).toLowerCase()); + keywords.push(t(`label.${contentItem.contentType}`).toLowerCase()); keywords.push(contentItem.title.toLowerCase()); return keywords.join(' '); } - resetFilters() { + const resetFilters = () => { return { contentTypes: [], hideUnpublishedContentItems: false, @@ -360,100 +274,148 @@ class ContentPage extends React.Component { }; } - renderFilterTags() { + const renderFilterTags = () => { let tags = []; - for (const contentType of this.state.filters.contentTypes) { + for (const contentType of filters.contentTypes) { const id = `contentTypes||${contentType}`; - tags.push({ id: id, label: this.props.t(`content.plural.${contentType}`)}); + tags.push({ id: id, label: t(`content.plural.${contentType}`)}); } - for (const issueType of this.state.filters.issueTypes) { + for (const issueType of filters.issueTypes) { const id = `issueTypes||${issueType}` - tags.push({ id: id, label: this.props.t(`label.plural.${issueType}`)}); + tags.push({ id: id, label: t(`label.plural.${issueType}`)}); } - for (const issueImpact of this.state.filters.issueImpacts) { + for (const issueImpact of filters.issueImpacts) { const id = `issueImpacts||${issueImpact}` - tags.push({ id: id, label: this.props.t(`label.filter.${issueImpact}`)}); + tags.push({ id: id, label: t(`label.filter.${issueImpact}`)}); } - for (const ruleId of this.state.filters.issueTitles) { + for (const ruleId of filters.issueTitles) { const id = `issueTitles||${ruleId}` - tags.push({ id: id, label: this.props.t(`rule.label.${ruleId}`) }); + tags.push({ id: id, label: t(`rule.label.${ruleId}`) }); } - for (const statusVal of this.state.filters.issueStatus) { + for (const statusVal of filters.issueStatus) { const id = `issueStatus||${statusVal}` - tags.push({ id: id, label: this.props.t(`label.filter.${statusVal}`) }); + tags.push({ id: id, label: t(`label.filter.${statusVal}`) }); } - if (this.state.filters.hideUnpublishedContentItems) { - tags.push({ id: `hideUnpublishedContentItems||true`, label: this.props.t(`label.hide_unpublished`) }); + if (filters.hideUnpublishedContentItems) { + tags.push({ id: `hideUnpublishedContentItems||true`, label: t(`label.hide_unpublished`) }); } - if (this.state.filters.easyIssues) { - tags.push({ id: `easyIssues||true`, label: this.props.t(`label.show_easy_issues`) }); + + if (filters.easyIssues) { + tags.push({ id: `easyIssues||true`, label: t(`label.show_easy_issues`) }); } return tags.map((tag, i) => { return ( - this.handleTagClick(tag.id, e)} - key={i} - elementRef={(node) => this[`tag${i}`] = node} - /> - )}); + handleTagClick(tag.id, e)} + key={i} + /> + ) + }); } - handleTagClick(tagId, e) { + const handleTagClick = (tagId, e) => { let [filterType, filterId] = tagId.split('||'); let results = null; let index = 0 switch (filterType) { case 'contentTypes': - index += this.state.filters.contentTypes.findIndex((val) => filterId == val) - results = this.state.filters.contentTypes.filter((val) => filterId !== val); + index += filters.contentTypes.findIndex((val) => filterId == val) + results = filters.contentTypes.filter((val) => filterId !== val); break; case 'issueTypes': - index = this.state.filters.contentTypes.length - index += this.state.filters.issueTypes.findIndex((val) => filterId == val) - results = this.state.filters.issueTypes.filter((val) => filterId !== val); + index = filters.contentTypes.length + index += filters.issueTypes.findIndex((val) => filterId == val) + results = filters.issueTypes.filter((val) => filterId !== val); break; case 'issueTitles': - index = this.state.filters.contentTypes.length + this.state.filters.issueTypes.length - index += this.state.filters.issueTitles.findIndex((val) => filterId == val) - results = this.state.filters.issueTitles.filter((val) => filterId !== val); + index = filters.contentTypes.length + filters.issueTypes.length + index += filters.issueTitles.findIndex((val) => filterId == val) + results = filters.issueTitles.filter((val) => filterId !== val); break; case 'issueStatus': - index = this.state.filters.contentTypes.length + this.state.filters.issueTypes.length + this.state.filters.issueTitles.length - index += this.state.filters.issueStatus.findIndex((val) => filterId == val) - results = this.state.filters.issueStatus.filter((val) => filterId != val); + index = filters.contentTypes.length + filters.issueTypes.length + filters.issueTitles.length + index += filters.issueStatus.findIndex((val) => filterId == val) + results = filters.issueStatus.filter((val) => filterId != val); break; case 'issueImpacts': - index = this.state.filters.contentTypes.length + this.state.filters.issueTypes.length + this.state.filters.issueTitles.length + this.state.filters.issueStatus.length - index += this.state.filters.issueImpacts.findIndex((val) => filterId == val) - results = this.state.filters.issueImpacts.filter((val) => filterId != val); + index = filters.contentTypes.length + filters.issueTypes.length + filters.issueTitles.length + filters.issueStatus.length + index += filters.issueImpacts.findIndex((val) => filterId == val) + results = filters.issueImpacts.filter((val) => filterId != val); break; case 'hideUnpublishedContentItems': - index = this.state.filters.contentTypes.length + this.state.filters.issueTypes.length + this.state.filters.issueTitles.length + this.state.filters.issueStatus.length + this.state.filters.issueImpacts.length + index = filters.contentTypes.length + filters.issueTypes.length + filters.issueTitles.length + filters.issueStatus.length + filters.issueImpacts.length results = false; break; } - this.handleFilter({ [filterType]: results }); - if (index - 1 >= 0) { - setTimeout(() => { - this[`tag${index - 1}`].focus() - }) - } else { - setTimeout(() => { - this.contentPageForm.focus() - }) - } + handleFilter({ [filterType]: results }); } -} -export default ContentPage; + const filteredRows = getFilteredContent() + + return ( + + + + {renderFilterTags()} + + + {trayOpen && } + {modalOpen && } + + {filteredRows.length === 0 && + } + + ) +} \ No newline at end of file diff --git a/assets/js/Components/ContentPageForm.js b/assets/js/Components/ContentPageForm.js index b06a78a5b..684afb15f 100644 --- a/assets/js/Components/ContentPageForm.js +++ b/assets/js/Components/ContentPageForm.js @@ -6,73 +6,59 @@ import { Flex } from '@instructure/ui-flex' import { ScreenReaderContent } from '@instructure/ui-a11y-content' import { SimpleSelect } from '@instructure/ui-simple-select' -class ContentPageForm extends React.Component { +export default function ContentPageForm({ t, searchTerm, handleSearchTerm, handleTableSettings, handleTrayToggle, tableSettings }) { + const options = ['10', '25', '50'] - constructor(props) { - super(props); - - } - - focus = () => { - this.filterButton.focus() - } - - render() { - const options = ['10', '25', '50']; - return ( - - - - - Search Term} - renderBeforeInput={} - placeholder={this.props.t('placeholder.keyword')} - onChange={this.props.handleSearchTerm} - value={this.props.searchTerm} - /> - - - { - this.props.handleTableSettings({ - rowsPerPage: value - }) - localStorage.setItem('rowsPerPage', value) - }} - width="13vw" - size="small" - > - {options.map((opt, index) => ( - - { opt } - - ))} - - - - - - {this.props.handleTrayToggle && - } - - - ); - } -} - -export default ContentPageForm; \ No newline at end of file + {options.map((opt, index) => ( + + { opt } + + ))} + + + + + + {handleTrayToggle && + } + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/ContentTrayForm.js b/assets/js/Components/ContentTrayForm.js index 0d0f06887..8124ce20a 100644 --- a/assets/js/Components/ContentTrayForm.js +++ b/assets/js/Components/ContentTrayForm.js @@ -7,181 +7,164 @@ import { View } from '@instructure/ui-view' import { Heading } from '@instructure/ui-heading' import IssueRuleSelect from './IssueRuleSelect'; -const issueTypes = [ - 'error', - 'suggestion' -] - -const issueStatus = [ - 'active', - 'fixed', - 'resolved' -] - -const issueImpacts = [ - 'visual', - 'auditory', - 'cognitive', - 'motor' -] - -class ContentTrayForm extends React.Component { - - constructor(props) { - super(props); - - this.handleContentTypeChange = this.handleContentTypeChange.bind(this) - this.handleIssueStatusChange = this.handleIssueStatusChange.bind(this) - this.handleUnpublishedContent = this.handleUnpublishedContent.bind(this) - this.handleIssueTypeChange = this.handleIssueTypeChange.bind(this) - this.handleIssueTitleChange = this.handleIssueTitleChange.bind(this) - this.handleIssueImpactChange = this.handleIssueImpactChange.bind(this) - this.handleEasyIssues = this.handleEasyIssues.bind(this) +export default function ContentTrayForm({ t, trayOpen, filters, handleTrayToggle, handleFilter, settings, report }) { + + const issueTypes = [ + 'error', + 'suggestion' + ] + + const issueStatus = [ + 'active', + 'fixed', + 'resolved' + ] + + const issueImpacts = [ + 'visual', + 'auditory', + 'cognitive', + 'motor' + ] + + const renderContentTypeCheckboxes = () => { + return settings.contentTypes.map((type) => ) } - - render() { - - return ( - - - - - {this.props.t('label.plural.filter')} - - - - - - - - {this.renderContentTypeCheckboxes()} - - - - - {this.renderIssueStatusCheckboxes()} - - - - - {this.renderIssueTypeCheckboxes()} - - - - - {this.renderIssueImpactCheckboxes()} - - - - - - - - - - - - - - ); + + const renderIssueStatusCheckboxes = () => { + return issueStatus.map((status) => ) } - - renderContentTypeCheckboxes() { - return this.props.settings.contentTypes.map((type) => ); + + const renderIssueTypeCheckboxes = () => { + return issueTypes.map((type) => ) } - - renderIssueStatusCheckboxes() { - return issueStatus.map((status) => ) + + const renderIssueImpactCheckboxes = () => { + return issueImpacts.map((impact) => ) } - - renderIssueTypeCheckboxes() { - return issueTypes.map((type) => ); + + const handleContentTypeChange = (values) => { + handleFilter({contentTypes: values}) } - - renderIssueImpactCheckboxes() { - return issueImpacts.map((impact) => ); + + const handleIssueStatusChange = (values) => { + handleFilter({issueStatus: values}) } - - handleContentTypeChange(values) { - this.props.handleFilter({contentTypes: values}); + + const handleIssueTypeChange = (values) => { + handleFilter({issueTypes: values}) } - - handleIssueStatusChange(values) { - this.props.handleFilter({issueStatus: values}) + + const handleIssueTitleChange = (values) => { + handleFilter({issueTitles: values}) } - - handleIssueTypeChange(values) { - this.props.handleFilter({issueTypes: values}); + + const handleIssueImpactChange = (values) => { + handleFilter({issueImpacts: values}) } - - handleIssueTitleChange(values) { - this.props.handleFilter({issueTitles: values}); + + const handleUnpublishedContent = () => { + handleFilter({ hideUnpublishedContentItems: !filters.hideUnpublishedContentItems }); } - - handleIssueImpactChange(values) { - this.props.handleFilter({issueImpacts: values}); + + const handleEasyIssues = () => { + handleFilter({ easyIssues: !filters.easyIssues }); } - - handleUnpublishedContent(e) { - this.props.handleFilter({ hideUnpublishedContentItems: !this.props.filters.hideUnpublishedContentItems }); - } - - handleEasyIssues(e) { - this.props.handleFilter({ easyIssues: !this.props.filters.easyIssues }); - } - - getRuleOptions() { + + const getRuleOptions = () => { let ruleOptions = {}; - - Object.values(this.props.report.issues).forEach( + + Object.values(report.issues).forEach( (issue) => { ruleOptions[issue.scanRuleId] = { id: issue.scanRuleId, - label: this.props.t(`rule.label.${issue.scanRuleId}`) + label: t(`rule.label.${issue.scanRuleId}`) }; } ); - + return Object.values(ruleOptions).sort((a, b) => (a.label.toLowerCase() < b.label.toLowerCase()) ? -1 : 1); } -} -export default ContentTrayForm; + return ( + + + + + {t('label.plural.filter')} + + + + + + + + {renderContentTypeCheckboxes()} + + + + + {renderIssueStatusCheckboxes()} + + + + + {renderIssueTypeCheckboxes()} + + + + + {renderIssueImpactCheckboxes()} + + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/FilesPage.js b/assets/js/Components/FilesPage.js index 70807e2ad..3bd42f14c 100644 --- a/assets/js/Components/FilesPage.js +++ b/assets/js/Components/FilesPage.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Button } from '@instructure/ui-buttons' import { IconCheckLine, IconEyeLine } from '@instructure/ui-icons' import SortableTable from './SortableTable' @@ -17,97 +17,72 @@ const fileTypes = [ 'xls', ] -class FilesPage extends React.Component { - constructor(props) { - super(props); - - this.headers = [ - {id: "status", text: '', alignText: "center"}, - {id: "fileName", text: this.props.t('label.file_name')}, - {id: "fileType", text: this.props.t('label.file_type')}, - {id: "fileSize", text: this.props.t('label.file_size'), format: this.formatFileSize}, - {id: "updated", text: this.props.t('label.file_updated'), format: this.formatDate}, - {id: "action", text: "", alignText: "end"} - ]; - - this.state = { - activeFile: null, - activeIndex: -1, - trayOpen: false, - modalOpen: false, - searchTerm: '', - filters: { - fileTypes: [], - hideReviewed: true - }, - tableSettings: { - sortBy: 'fileName', - ascending: true, - pageNum: 0, - rowsPerPage: (localStorage.getItem('rowsPerPage')) ? localStorage.getItem('rowsPerPage') : '10' - } - } - - this.handleTrayToggle = this.handleTrayToggle.bind(this) - this.handleSearchTerm = this.handleSearchTerm.bind(this) - this.handleTableSettings = this.handleTableSettings.bind(this) - this.handleFilter = this.handleFilter.bind(this) - this.handleReviewClick = this.handleReviewClick.bind(this) - this.handleActiveFile = this.handleActiveFile.bind(this) - } - - componentDidMount() { - } - - handleSearchTerm = (e, val) => { - this.setState({searchTerm: val, tableSettings: Object.assign({}, this.state.tableSettings, {pageNum: 0})}); +export default function FilesPage({ t, report, settings, handleFileSave }) { + const headers = [ + {id: "status", text: '', alignText: "center"}, + {id: "fileName", text: t('label.file_name')}, + {id: "fileType", text: t('label.file_type')}, + {id: "fileSize", text: t('label.file_size'), format: formatFileSize}, + {id: "updated", text: t('label.file_updated'), format: formatDate}, + {id: "action", text: "", alignText: "end"} + ]; + + const [activeFile, setActiveFile] = useState(null) + const [activeIndex, setActiveIndex] = useState(-1) + const [filteredFiles, setFilteredFiles] = useState([]) + const [trayOpen, setTrayOpen] = useState(false) + const [modalOpen, setModalOpen] = useState(false) + const [searchTerm, setSearchTerm] = useState('') + const [filters, setFilters] = useState({ + fileTypes: [], + hideReviewed: true + }) + const [tableSettings, setTableSettings] = useState({ + sortBy: 'fileName', + ascending: true, + pageNum: 0, + rowsPerPage: (localStorage.getItem('rowsPerPage')) ? localStorage.getItem('rowsPerPage') : '10' + }) + + const handleSearchTerm = (e, val) => { + setSearchTerm(val) + setTableSettings({...tableSettings, pageNum: 0}) } - handleTrayToggle = (e, val) => { - this.setState({trayOpen: !this.state.trayOpen}); + const handleTrayToggle = (e, val) => { + setTrayOpen(!trayOpen) } - handleFilter = (filter) => { - this.setState({ - filters: Object.assign({}, this.state.filters, filter), - tableSettings: { - sortBy: 'fileName', - ascending: true, - pageNum: 0, - } + const handleFilter = (filter) => { + setFilters({...filters, ...filter}) + setTableSettings({ + sortBy: 'fileName', + ascending: true, + pageNum: 0, + rowsPerPage: tableSettings.rowsPerPage }) } - handleTableSettings = (setting) => { - this.setState({ - tableSettings: Object.assign({}, this.state.tableSettings, setting) - }); + const handleTableSettings = (setting) => { + setTableSettings({...tableSettings, ...setting}) } - handleActiveFile(newFile, newIndex) { - this.setState({ - activeFile: newFile, - activeIndex: Number(newIndex) - }) + const handleActiveFile = (newFile, newIndex) => { + setActiveFile(newFile) + setActiveIndex(Number(newIndex)) } - handleReviewClick(activeFile) { - this.setState({ - modalOpen: true, - activeFile: activeFile - }) + const handleReviewClick = (activeFile) => { + setModalOpen(true) + setActiveFile(activeFile) } - handleCloseButton = () => { - this.setState({ - modalOpen: false - }) + const handleCloseButton = () => { + setModalOpen(false) } - getFilteredFiles = () => { - const report = this.props.report; - const filters = this.state.filters; - const { sortBy, ascending } = this.state.tableSettings + const getFilteredFiles = () => { + const { sortBy, ascending } = tableSettings let filteredList = []; let fileList = Object.assign({}, report.files); @@ -126,8 +101,8 @@ class FilesPage extends React.Component { } // Filter by search term - if (this.state.searchTerm !== '') { - const searchTerms = this.state.searchTerm.toLowerCase().split(' '); + if (searchTerm !== '') { + const searchTerms = searchTerm.toLowerCase().split(' '); if (Array.isArray(searchTerms)) { for (let term of searchTerms) { @@ -141,12 +116,12 @@ class FilesPage extends React.Component { let status if (file.reviewed) { status = <> - {this.props.t('label.file.reviewed')} + {t('label.file.reviewed')} } else { status = <> - {this.props.t('label.file.needs_review')} + {t('label.file.needs_review')} } @@ -162,14 +137,13 @@ class FilesPage extends React.Component { updated: file.updated, action: , - onClick: () => this.handleReviewClick(file), + onClick={() => handleReviewClick(file)} + textAlign="center" >{t('label.review')}, + onClick: () => handleReviewClick(file), } ); } - filteredList.sort((a, b) => { if (isNaN(a[sortBy]) || isNaN(b[sortBy])) { return (a[sortBy].toLowerCase() < b[sortBy].toLowerCase()) ? -1 : 1; @@ -185,127 +159,67 @@ class FilesPage extends React.Component { return filteredList; } - - render() { - const filteredFiles = this.getFilteredFiles() - const report = this.props.report - - return ( - - this.filesPageForm = node} - handleTableSettings={this.handleTableSettings} - tableSettings={this.state.tableSettings} - /> - - {this.renderFilterTags()} - - - {this.state.trayOpen && } - {this.state.modalOpen && - } - - {filteredFiles.length === 0 && - } - - ) - } - - resetFilters() { + + const resetFilters = () => { return { fileTypes: [], hideReviewed: false, }; } - renderFilterTags() { + const renderFilterTags = () => { let tags = []; - for (const fileType of this.state.filters.fileTypes) { + for (const fileType of filters.fileTypes) { const id = `fileTypes||${fileType}`; - tags.push({ id: id, label: this.props.t(`label.mime.${fileType}`) }); + tags.push({ id: id, label: t(`label.mime.${fileType}`) }); } - if (this.state.filters.hideReviewed) { - tags.push({ id: `hideReviewed||true`, label: this.props.t(`label.hide_reviewed`)}); + if (filters.hideReviewed) { + tags.push({ id: `hideReviewed||true`, label: t(`label.hide_reviewed`)}); } return tags.map((tag, i) => ( this.handleTagClick(tag.id, e)} + onClick={(e) => handleTagClick(tag.id, e)} key={i} - elementRef={(node) => this[`tag${i}`] = node} + // elementRef={(node) => this[`tag${i}`] = node} + elementRef={() => { React.createRef() }} /> )); } - handleTagClick(tagId, e) { + const handleTagClick = (tagId, e) => { let [filterType, filterId] = tagId.split('||'); let results = null; let index = 0 switch (filterType) { case 'fileTypes': - index += this.state.filters.fileTypes.findIndex((val) => filterId == val) - results = this.state.filters.fileTypes.filter((val) => filterId !== val); + index += filters.fileTypes.findIndex((val) => filterId == val) + results = filters.fileTypes.filter((val) => filterId !== val); break; case 'hideReviewed': - index = this.state.filters.fileTypes.length + index = filters.fileTypes.length results = false; break; } - this.handleFilter({ [filterType]: results }); + handleFilter({ [filterType]: results }); if (index - 1 >= 0) { setTimeout(() => { this[`tag${index - 1}`].focus() }) } else { setTimeout(() => { - this.filesPageForm.focus() + filesPageForm.focus() }) } } - formatFileSize(size) { + const formatFileSize = (size) => { if (!size) { return 'N/A' } @@ -321,11 +235,69 @@ class FilesPage extends React.Component { return size; } - formatDate(date) { + const formatDate = (date) => { let parts = date.split('T') return parts[0] } -} -export default FilesPage; + useEffect(() => { + setFilteredFiles(getFilteredFiles()) + }, [report, filters, searchTerm, tableSettings]) + + return ( + + filesPageForm = node} + handleTableSettings={handleTableSettings} + tableSettings={tableSettings} + /> + + {renderFilterTags()} + + + {trayOpen && } + {modalOpen && + } + + {filteredFiles.length === 0 && + } + + ) +} \ No newline at end of file diff --git a/assets/js/Components/FilesPageForm.js b/assets/js/Components/FilesPageForm.js index 3abd9a3ff..8e3b8c4b7 100644 --- a/assets/js/Components/FilesPageForm.js +++ b/assets/js/Components/FilesPageForm.js @@ -6,72 +6,59 @@ import { Flex } from '@instructure/ui-flex' import { ScreenReaderContent } from '@instructure/ui-a11y-content' import { SimpleSelect } from '@instructure/ui-simple-select' -class FilesPageForm extends React.Component { +export default function FilesPageForm({t, searchTerm, handleSearchTerm, handleTableSettings, tableSettings, handleTrayToggle}) { - constructor(props) { - super(props); + const options = ['10', '25', '50']; - } - - focus = () => { - this.buttonRef.focus() - } - - render() { - const options = ['10', '25', '50']; - return ( - - - - - Search Term} - renderBeforeInput={} - placeholder={this.props.t('placeholder.keyword')} - onChange={this.props.handleSearchTerm} - value={this.props.searchTerm} - /> - - - { - this.props.handleTableSettings({ - rowsPerPage: value - }) - localStorage.setItem('rowsPerPage', value) - }} - width="13vw" - size="small" - > - {options.map((opt, index) => ( - - { opt } - - ))} - - - - - - - - - ); - } -} - -export default FilesPageForm; \ No newline at end of file + return ( + + + + + Search Term} + renderBeforeInput={} + placeholder={t('placeholder.keyword')} + onChange={handleSearchTerm} + value={searchTerm} + /> + + + { + handleTableSettings({ + rowsPerPage: value + }) + localStorage.setItem('rowsPerPage', value) + }} + width="13vw" + size="small" + > + {options.map((opt, index) => ( + + { opt } + + ))} + + + + + + + + + ); +} \ No newline at end of file diff --git a/assets/js/Components/FilesTrayForm.js b/assets/js/Components/FilesTrayForm.js index e0f170d59..df0b97b30 100644 --- a/assets/js/Components/FilesTrayForm.js +++ b/assets/js/Components/FilesTrayForm.js @@ -6,82 +6,69 @@ import { Tray } from '@instructure/ui-tray' import { View } from '@instructure/ui-view' import { Heading } from '@instructure/ui-heading' -class FilesTrayForm extends React.Component { +export default function FilesTrayForm({t, trayOpen, handleTrayToggle, filters, handleFilter, fileTypes}) { - constructor(props) { - super(props); - - this.handleFileTypeChange = this.handleFileTypeChange.bind(this); - this.handleHideReviewed = this.handleHideReviewed.bind(this); + const renderFileTypeCheckboxes = () => { + return fileTypes.map((type) => ); } - render() { - - return ( - - - - - {this.props.t('label.plural.filter')} - - - - - - - - {this.renderFileTypeCheckboxes()} - - - - - - - - - - - ); + const handleFileTypeChange = (values) => { + handleFilter({fileTypes: values}) } - renderFileTypeCheckboxes() { - return this.props.fileTypes.map((type) => ); + const handleUnpublishedFiles = (e) => { + handleFilter({ hideUnpublishedFiles: !filters.hideUnpublishedFiles }) } - handleFileTypeChange(values) { - this.props.handleFilter({fileTypes: values}); - } - - handleUnpublishedFiles(e) { - this.props.handleFilter({ hideUnpublishedFiles: !this.props.filters.hideUnpublishedFiles }); + const handleHideReviewed = (e) => { + handleFilter({ hideReviewed: !filters.hideReviewed }) } - handleHideReviewed(e) { - this.props.handleFilter({ hideReviewed: !this.props.filters.hideReviewed }); - } - -} - -export default FilesTrayForm; \ No newline at end of file + return ( + + + + + {t('label.plural.filter')} + + + + + + + + {renderFileTypeCheckboxes()} + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/assets/js/Components/Forms/ContrastForm.js b/assets/js/Components/Forms/ContrastForm.js index 14b2a016d..df91e6932 100644 --- a/assets/js/Components/Forms/ContrastForm.js +++ b/assets/js/Components/Forms/ContrastForm.js @@ -316,7 +316,12 @@ export default class ContrastForm extends React.Component { if (element.style.backgroundColor) { return Contrast.standardizeColor(element.style.backgroundColor) - } + } + else if (metadata.messageArgs) { + // TODO: check if 4th argument exists + // (Equal Access) text_contrast_sufficient: The 4th index in messageArgs is the background color + return metadata.messageArgs[4] + } else { return (metadata.backgroundColor) ? Contrast.standardizeColor(metadata.backgroundColor) : this.props.settings.backgroundColor } @@ -332,6 +337,10 @@ export default class ContrastForm extends React.Component { if (element.style.color) { return Contrast.standardizeColor(element.style.color) } + else if (metadata.messageArgs) { + // (Equal Access) text_contrast_sufficient: The 3rd index in messageArgs is the foreground color + return metadata.messageArgs[3] + } else { return (metadata.color) ? Contrast.standardizeColor(metadata.color) : this.props.settings.textColor } diff --git a/assets/js/Components/Forms/LabelForm.js b/assets/js/Components/Forms/LabelForm.js new file mode 100644 index 000000000..00e6c9cf4 --- /dev/null +++ b/assets/js/Components/Forms/LabelForm.js @@ -0,0 +1,151 @@ +import React, { useEffect, useState } from 'react' +import { View } from '@instructure/ui-view' +import { TextInput } from '@instructure/ui-text-input' +import { Button } from '@instructure/ui-buttons' +import { IconCheckMarkLine } from '@instructure/ui-icons' +import { Checkbox } from '@instructure/ui-checkbox' +import { Spinner } from '@instructure/ui-spinner' +import * as Html from '../../Services/Html' + +export default function LabelForm(props) { + + let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml + + if (props.activeIssue.status === '1') { + html = props.activeIssue.newHtml + } + + let element = Html.toElement(html) + + const [textInputValue, setTextInputValue] = useState(element ? Html.getAttribute(element, "aria-label") : "") + // const [deleteLabel, setDeleteLabel] = useState(!element && (props.activeIssue.status === "1")) + const [textInputErrors, setTextInputErrors] = useState([]) + + let formErrors = [] + + useEffect(() => { + let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml + if (props.activeIssue.status === 1) { + html = props.activeIssue.newHtml + } + + let element = Html.toElement(html) + setTextInputValue(element ? Html.getAttribute(element, "aria-label") : "") + // setDeleteLabel(!element && props.activeIssue.status === 1) + + formErrors = [] + + }, [props.activeIssue]) + + useEffect(() => { + handleHtmlUpdate() + }, [textInputValue]) + + const handleHtmlUpdate = () => { + let updatedElement = Html.toElement(html) + + updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue) + + // if (deleteLabel) { + // updatedElement = Html.removeAttribute(updatedElement, "aria-label") + // } + // else { + // updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue) + // } + + let issue = props.activeIssue + issue.newHtml = Html.toString(updatedElement) + props.handleActiveIssue(issue) + + } + + const handleButton = () => { + formErrors = [] + + // if (!deleteLabel) { + // checkTextNotEmpty() + // } + + checkTextNotEmpty() + checkLabelIsUnique() + + if (formErrors.length > 0) { + setTextInputErrors(formErrors) + } + else { + props.handleIssueSave(props.activeIssue) + } + } + + const handleInput = (event) => { + setTextInputValue(event.target.value) + // handleHtmlUpdate() + } + + // const handleCheckbox = () => { + // setDeleteLabel(!deleteLabel) + // // handleHtmlUpdate() + // } + + const checkTextNotEmpty = () => { + const text = textInputValue.trim().toLowerCase() + if (text === '') { + formErrors.push({ text: "Empty label text.", type: "error" }) + } + } + + const checkLabelIsUnique = () => { + // in the case of aria_*_label_unique, messageArgs (from metadata) should have the offending label (at the first index) + // i guess we could get it from the aria-label itself as well... + const issue = props.activeIssue + const metadata = issue.metadata ? JSON.parse(issue.metadata) : {} + const labelFromMessageArgs = metadata.messageArgs ? metadata.messageArgs[0] : null + const text = textInputValue.trim().toLowerCase() + + if (labelFromMessageArgs) { + if (text == labelFromMessageArgs) { + formErrors.push({ text: "Cannot reuse label text.", type: "error" }) + } + } + + } + + const pending = props.activeIssue && props.activeIssue.pending == "1" + const buttonLabel = pending ? "form.processing" : "form.submit" + + return ( + + + + + {/* + + + + */} + + + + + ); +} \ No newline at end of file diff --git a/assets/js/Components/Forms/QuoteForm.js b/assets/js/Components/Forms/QuoteForm.js new file mode 100644 index 000000000..37b956b9c --- /dev/null +++ b/assets/js/Components/Forms/QuoteForm.js @@ -0,0 +1,166 @@ +import React, { useEffect, useState } from 'react' +import { View } from '@instructure/ui-view' +import { TextInput } from '@instructure/ui-text-input' +import { Button } from '@instructure/ui-buttons' +import { IconCheckMarkLine } from '@instructure/ui-icons' +import { Checkbox } from '@instructure/ui-checkbox' +import { Spinner } from '@instructure/ui-spinner' +import * as Html from '../../Services/Html' +import { SimpleSelect } from '@instructure/ui-simple-select' + +// TODO: not finished + +export default function QuoteForm(props) { + + let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml + + if (props.activeIssue.status === '1') { + html = props.activeIssue.newHtml + } + + let element = Html.toElement(html) + + const [textInputValue, setTextInputValue] = useState(element ? Html.getAttribute(element, "aria-label") : "") + const [deleteQuotes, setRemoveQuotes] = useState(!element && (props.activeIssue.status === "1")) + const [textInputErrors, setTextInputErrors] = useState([]) + + let formErrors = [] + + useEffect(() => { + let html = props.activeIssue.newHtml ? props.activeIssue.newHtml : props.activeIssue.sourceHtml + if (props.activeIssue.status === 1) { + html = props.activeIssue.newHtml + } + + let element = Html.toElement(html) + setTextInputValue(element ? Html.getAttribute(element, "aria-label") : "") + // setRemoveQuotes(!element && props.activeIssue.status === 1) + + formErrors = [] + + }, [props.activeIssue]) + + useEffect(() => { + handleHtmlUpdate() + }, [textInputValue]) + + const handleHtmlUpdate = () => { + let updatedElement = Html.toElement(html) + + updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue) + + // if (deleteQuotes) { + // updatedElement = Html.removeAttribute(updatedElement, "aria-label") + // } + // else { + // updatedElement = Html.setAttribute(updatedElement, "aria-label", textInputValue) + // } + + let issue = props.activeIssue + issue.newHtml = Html.toString(updatedElement) + props.handleActiveIssue(issue) + + } + + const handleButton = () => { + formErrors = [] + + // if (!deleteQuotes) { + // checkTextNotEmpty() + // } + + checkTextNotEmpty() + checkLabelIsUnique() + + if (formErrors.length > 0) { + setTextInputErrors(formErrors) + } + else { + props.handleIssueSave(props.activeIssue) + } + } + + const handleInput = (event) => { + setTextInputValue(event.target.value) + // handleHtmlUpdate() + } + + const handleCheckbox = () => { + setRemoveQuotes(!deleteQuotes) + // handleHtmlUpdate() + } + + const checkTextNotEmpty = () => { + const text = textInputValue.trim().toLowerCase() + if (text === '') { + formErrors.push({ text: "Empty label text.", type: "error" }) + } + } + + const checkLabelIsUnique = () => { + // in the case of aria_*_label_unique, messageArgs (from metadata) should have the offending label (at the first index) + // i guess we could get it from the aria-label itself as well... + const issue = props.activeIssue + const metadata = issue.metadata ? JSON.parse(issue.metadata) : {} + const labelFromMessageArgs = metadata.messageArgs ? metadata.messageArgs[0] : null + const text = textInputValue.trim().toLowerCase() + + if (labelFromMessageArgs) { + if (text == labelFromMessageArgs) { + formErrors.push({ text: "Cannot reuse label text.", type: "error" }) + } + } + + } + + const pending = props.activeIssue && props.activeIssue.pending == "1" + const buttonLabel = pending ? "form.processing" : "form.submit" + + // TODO: use props.t (from en/es.json) to display text for renderLabel, etc + return ( + + + + + -- Choose -- + + + + + + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/assets/js/Components/Forms/StyleMisuseForm.js b/assets/js/Components/Forms/StyleMisuseForm.js new file mode 100644 index 000000000..ace162bbc --- /dev/null +++ b/assets/js/Components/Forms/StyleMisuseForm.js @@ -0,0 +1,183 @@ +import React, { act, useEffect, useState } from 'react' +import { View } from '@instructure/ui-view' +import { TextInput } from '@instructure/ui-text-input' +import { Button } from '@instructure/ui-buttons' +import { IconCheckMarkLine } from '@instructure/ui-icons' +import { Checkbox } from '@instructure/ui-checkbox' +import { Spinner } from '@instructure/ui-spinner' +import * as Html from '../../Services/Html' +import * as Contrast from '../../Services/Contrast' + +export default function StyleMisuseForm(props) { + const [useBold, setUseBold] = useState(isBold()) + const [useItalics, setUseItalics] = useState(isItalicized()) + const [removeStyling, setRemoveStyling] = useState(false) + const [checkBoxErrors, setCheckBoxErrors] = useState([]) + const [styleAttribute, setStyleAttribute] = useState(Html.getAttribute(Html.getIssueHtml(props.activeIssue), "style")) + + console.log(styleAttribute) + + let formErrors = [] + + useEffect(() => { + updatePreview() + }, []) + + useEffect(() => { + setUseBold(isBold()) + setUseItalics(isItalicized()) + setCheckBoxErrors([]) + + formErrors = [] + }, [props.activeIssue]) + + useEffect(() => { + updatePreview() + }, [useBold, useItalics, removeStyling]) + + function handleBoldToggle() { + setUseBold(!useBold) + updatePreview() + } + + function handleItalicsToggle() { + setUseItalics(!useItalics) + updatePreview() + } + + function handleStyleToggle() { + setRemoveStyling(!removeStyling) + console.log("style tag:") + console.log(styleAttribute) + updatePreview() + } + + function handleSubmit() { + let issue = props.activeIssue + + if (cssEmphasisIsValid(issue)) { + let issue = props.activeIssue + issue.newHtml = Contrast.convertHtmlRgb2Hex(issue.newHtml) + props.handleIssueSave(issue) + } + else { + // push errors + formErrors = [] + formErrors.push({ text: `${props.t('form.contrast.must_select')}` , type: 'error' }) + + setCheckBoxErrors(formErrors) + } + } + + function processHtml(html) { + let element = Html.toElement(html) + + // Clean up tags + Html.removeTag(element, 'strong') + Html.removeTag(element, 'em') + + element.innerHTML = (useBold) ? `${element.innerHTML}` : element.innerHTML + element.innerHTML = (useItalics) ? `${element.innerHTML}` : element.innerHTML + + if (removeStyling) { + Html.removeAttribute(element, "style") + } + else { + Html.setAttribute(element, "style", styleAttribute) + } + + return Html.toString(element) + } + + function updatePreview() { + let issue = props.activeIssue + const html = Html.getIssueHtml(props.activeIssue) + + issue.newHtml = processHtml(html) + props.handleActiveIssue(issue) + } + + function isBold() { + const issue = props.activeIssue + const metadata = (issue.metadata) ? JSON.parse(issue.metadata) : {} + const html = Html.getIssueHtml(props.activeIssue) + const element = Html.toElement(html) + + return ((Html.hasTag(element, 'strong')) || (metadata.fontWeight === 'bold')) + } + + function isItalicized() { + const issue = props.activeIssue + const metadata = (issue.metadata) ? JSON.parse(issue.metadata) : {} + const html = Html.getIssueHtml(props.activeIssue) + const element = Html.toElement(html) + + return ((Html.hasTag(element, 'em')) || (metadata.fontStyle == 'italic')) + } + + function hasStyleTag() { + const html = Html.getIssueHtml(props.activeIssue) + const element = Html.toElement(html) + + console.log("checking style attribute") + console.log(Html.getAttribute(element, "style")) + + return true + + // return (Html.getAttribute(element, "style") != null) + } + + function cssEmphasisIsValid(issue) { + if (issue.scanRuleId === 'style_color_misuse') { + if (!useBold && !useItalics) { + return false + } + } + return true + } + + const pending = (props.activeIssue && (props.activeIssue.pending == '1')) + const buttonLabel = (pending) ? 'form.processing' : 'form.submit' + + return ( + + + + + + + + + + + + + + {/* TOOD: use props.t */} + + + + + + + {props.activeIssue.recentlyUpdated && + + + {props.t('label.fixed')} + + } + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/Forms/UfixitReviewOnly.js b/assets/js/Components/Forms/UfixitReviewOnly.js index 17c88fbc2..513b973b5 100644 --- a/assets/js/Components/Forms/UfixitReviewOnly.js +++ b/assets/js/Components/Forms/UfixitReviewOnly.js @@ -1,19 +1,31 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' import { View } from '@instructure/ui-view' import { Text } from '@instructure/ui-text' -class UfixitReviewOnly extends React.Component { - constructor(props) { - super(props) - } +export default function UfixitReviewOnly(props) { + function getMetadata() { + const issue = props.activeIssue + const metadata = issue.metadata ? JSON.parse(issue.metadata) : {} + return metadata + } + + const metadata = getMetadata() + const [message, setMessage] = useState("") - render() { - return ( - - {this.props.t('label.review_only')} - - ) + useEffect(() => { + if (metadata.message) { + // when using equal access, we should have metadata.message + setMessage(metadata.message) + } + else { + // otherwise, in phpally, we display the default "review" text + setMessage(props.t("label.review_only")) } -} + }, [metadata]) -export default UfixitReviewOnly \ No newline at end of file + return ( + + {message} + + ) +} \ No newline at end of file diff --git a/assets/js/Components/Header.js b/assets/js/Components/Header.js index ff5f492c6..aa6d9edb8 100644 --- a/assets/js/Components/Header.js +++ b/assets/js/Components/Header.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState, useEffect } from 'react' import Logo from '../../mediaAssets/udoit_logo.svg' import Classes from '../../css/header.css' import { View } from '@instructure/ui-view' @@ -8,73 +8,62 @@ import { Menu } from '@instructure/ui-menu' import { AppNav } from '@instructure/ui-navigation' import Api from '../Services/Api' -class Header extends React.Component { +export default function Header({ t, settings, hasNewReport, navigation, handleNavigation, handleCourseRescan, handleFullCourseRescan, handleModal }) { + const [pdfUrl, setPdfUrl] = useState('') - constructor(props) { - super(props); - - this.state = { - showPopover: false - } - - this.getPdfUrl = this.getPdfUrl.bind(this) + const getPdfUrl = () => { + let api = new Api(settings) + return api.getPdfUrl() } - render() { - const pdfUrl = this.getPdfUrl() + useEffect(() => { + setPdfUrl(getPdfUrl()) + }, []) - return ( -
- - UDOIT - - } - visibleItemsCount={3} - renderAfterItems={ - } - > - this.props.handleModal('about')}>{this.props.t('menu.about')} - this.props.handleNavigation('reports')}>{this.props.t('menu.reports')} - {/* this.handleMoreNav('settings')}>{this.props.t('menu.settings')} */} - - {this.props.t('menu.scan_course')} - {this.props.t('menu.full_rescan')} - - {this.props.t('menu.download_pdf')} - - } + return ( +
+ + UDOIT + + } + visibleItemsCount={3} + renderAfterItems={ + } > - this.props.handleNavigation('summary')} /> - this.props.handleNavigation('content')} /> - this.props.handleNavigation('files')} /> + handleModal('about')}>{t('menu.about')} + handleNavigation('reports')}>{t('menu.reports')} - -
- ) - } - - getPdfUrl() { - let api = new Api(this.props.settings) - return api.getPdfUrl() - } -} + + {t('menu.scan_course')} + {t('menu.full_rescan')} + + {t('menu.download_pdf')} + + } + > + handleNavigation('summary')} /> + handleNavigation('content')} /> + handleNavigation('files')} /> -export default Header +
+
+ ) +} \ No newline at end of file diff --git a/assets/js/Components/IssueRuleSelect.js b/assets/js/Components/IssueRuleSelect.js index 4774e89fe..bed30803f 100644 --- a/assets/js/Components/IssueRuleSelect.js +++ b/assets/js/Components/IssueRuleSelect.js @@ -1,242 +1,206 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Select } from '@instructure/ui-select' import { Tag } from '@instructure/ui-tag' import { Alert } from '@instructure/ui-alerts' import { View } from '@instructure/ui-view' -class IssueRuleSelect extends React.Component { - constructor(props) { - super(props); +export default function IssueRuleSelect({ t, options, issueTitles, handleIssueTitleChange }) { - this.state = { - isShowingOptions: false, - inputValue: '', - highlightedOptionId: null, - selectedOptionIds: this.props.issueTitles, - filteredOptions: this.props.options, - } - } - - getOptionById (queryId) { - return this.props.options.find(({ id }) => id === queryId) + const [ isShowingOptions, setIsShowingOptions ] = useState(false) + const [ inputValue, setInputValue ] = useState('') + const [ highlightedOptionId, setHighlightedOptionId ] = useState(null) + const [ selectedOptionIds, setSelectedOptionIds ] = useState(issueTitles) + const [ filteredOptions, setFilteredOptions ] = useState(options) + const [ announcement, setAnnouncement ] = useState('') + + const getOptionById = (queryId) => { + return options.find(({ id }) => id === queryId) } - getOptionsChangedMessage (newOptions) { - let message = newOptions.length !== this.state.filteredOptions.length - ? `${newOptions.length} ${this.props.t('options.available')}.` // options changed, announce new total + const getOptionsChangedMessage = (newOptions) => { + let message = newOptions.length !== filteredOptions.length + ? `${newOptions.length} ${t('options.available')}.` // options changed, announce new total : null // options haven't changed, don't announce if (message && newOptions.length > 0) { // options still available - if (this.state.highlightedOptionId !== newOptions[0].id) { + if (highlightedOptionId !== newOptions[0].id) { // highlighted option hasn't been announced - const option = this.getOptionById(newOptions[0].id).label + const option = getOptionById(newOptions[0].id).label message = `${option}. ${message}` } } return message } - filterOptions = (value) => { - const { selectedOptionIds } = this.state - return this.props.options.filter(option => ( + const filterOptions = (value) => { + return options.filter(option => ( selectedOptionIds.indexOf(option.id) === -1 // ignore selected options removed from list && option.label.toLowerCase().includes(value.toLowerCase()) )) } - matchValue() { - const { - filteredOptions, - inputValue, - highlightedOptionId, - selectedOptionIds - } = this.state + const matchValue = () => { // an option matching user input exists if (filteredOptions.length === 1) { const onlyOption = filteredOptions[0] // automatically select the matching option if (onlyOption.label.toLowerCase() === inputValue.toLowerCase()) { - return { - inputValue: '', - selectedOptionIds: [...selectedOptionIds, onlyOption.id], - filteredOptions: this.filterOptions('') - } + setInputValue('') + setSelectedOptionIds([...selectedOptionIds, onlyOption.id]) + setFilteredOptions(filterOptions('')) } } // input value is from highlighted option, not user input // clear input, reset options if (highlightedOptionId) { - if (inputValue === this.getOptionById(highlightedOptionId).label) { - return { - inputValue: '', - filteredOptions: this.filterOptions('') - } + if (inputValue === getOptionById(highlightedOptionId).label) { + setInputValue('') + setFilteredOptions(filterOptions('')) } } } - handleShowOptions = (event) => { - this.setState({ isShowingOptions: true }) + const handleShowOptions = () => { + setIsShowingOptions(true) } - handleHideOptions = (event) => { - this.setState({ - isShowingOptions: false, - ...this.matchValue() - }) + const handleHideOptions = () => { + setIsShowingOptions(false) + matchValue() } - handleBlur = (event) => { - this.setState({ - highlightedOptionId: null - }) + const handleBlur = () => { + setHighlightedOptionId(null) } - handleHighlightOption = (event, { id }) => { + const handleHighlightOption = (event, { id }) => { event.persist() - const option = this.getOptionById(id) + const option = getOptionById(id) if (!option) return // prevent highlighting empty option - this.setState((state) => ({ - highlightedOptionId: id, - inputValue: event.type === 'keydown' ? option.label : state.inputValue, - announcement: option.label - })) + setHighlightedOptionId(id) + setInputValue(event.type === 'keydown' ? option.label : inputValue) + + setHighlightedOptionId(id) + setInputValue(event.type === 'keydown' ? option.label : inputValue) + setAnnouncement(option.label) } - handleSelectOption = (event, { id }) => { - const option = this.getOptionById(id) + const handleSelectOption = (event, { id }) => { + const option = getOptionById(id) if (!option) return // prevent selecting of empty option - this.setState((state) => ({ - selectedOptionIds: [...state.selectedOptionIds, id], - highlightedOptionId: null, - filteredOptions: this.filterOptions(''), - inputValue: '', - isShowingOptions: false, - announcement: `${option.label} ${this.props.t('label.selected.list_collapsed')}.` - })) - - this.props.handleIssueTitleChange([...this.state.selectedOptionIds, id]) + setSelectedOptionIds([...selectedOptionIds, id]) + setHighlightedOptionId(null) + setFilteredOptions(filterOptions('')) + setInputValue('') + setIsShowingOptions(false) + setAnnouncement(`${option.label} ${t('label.selected.list_collapsed')}.`) + + handleIssueTitleChange([...selectedOptionIds, id]) } - handleInputChange = (event) => { + const handleInputChange = (event) => { const value = event.target.value - const newOptions = this.filterOptions(value) - this.setState({ - inputValue: value, - filteredOptions: newOptions, - highlightedOptionId: newOptions.length > 0 ? newOptions[0].id : null, - isShowingOptions: true, - announcement: this.getOptionsChangedMessage(newOptions) - }) + const newOptions = filterOptions(value) + + setInputValue(value) + setFilteredOptions(newOptions) + setHighlightedOptionId(newOptions.length > 0 ? newOptions[0].id : null) + setIsShowingOptions(true) + setAnnouncement(getOptionsChangedMessage(newOptions)) } - handleKeyDown = (event) => { - const { selectedOptionId, inputValue } = this.state + const handleKeyDown = (event) => { + if (event.keyCode === 8) { // when backspace key is pressed if (inputValue === '' && selectedOptionId.length > 0) { // remove last selected option, if input has no entered text - this.setState((state) => ({ - highlightedOptionId: null, - selectedOptionIds: state.selectedOptionIds.slice(0, -1) - })) + setHighlightedOptionId(null) + setSelectedOptionIds(selectedOptionIds.slice(0, -1)) } } } + // remove a selected option tag - dismissTag (e, tag) { + const dismissTag = (e, tag) => { // prevent closing of list e.stopPropagation() e.preventDefault() - const newSelection = this.state.selectedOptionIds.filter((id) => id !== tag) - this.setState({ - selectedOptionIds: newSelection, - highlightedOptionId: null - }, () => { - this.inputRef.focus() - }) + const newSelection = selectedOptionIds.filter((id) => id !== tag) + + setSelectedOptionIds(newSelection) + setHighlightedOptionId(null) + + // this?.inputRef.focus() - this.props.handleIssueTitleChange(newSelection) + handleIssueTitleChange(newSelection) } // render tags when multiple options are selected - renderTags () { - const { selectedOptionIds } = this.state + const renderTags = () => { + return selectedOptionIds.map((id, index) => ( this.dismissTag(e, id)} + onClick={(e) => dismissTag(e, id)} /> )) } - render () { - const { - inputValue, - isShowingOptions, - highlightedOptionId, - selectedOptionIds, - filteredOptions, - announcement - } = this.state - - return ( - - - document.getElementById('flash-messages')} - liveRegionPoliteness="polite" - isLiveRegionAtomic - screenReaderOnly - > - { announcement } - - - {selectedOptionIds.length > 0 ? this.renderTags() : null} - + return ( + + + document.getElementById('flash-messages')} + liveRegionPoliteness="polite" + isLiveRegionAtomic + screenReaderOnly + > + { announcement } + + + {selectedOptionIds.length > 0 ? renderTags() : null} - ) - } -} - -export default IssueRuleSelect; \ No newline at end of file + + ) +} \ No newline at end of file diff --git a/assets/js/Components/MessageTray.js b/assets/js/Components/MessageTray.js index ad15426a8..b903300e2 100644 --- a/assets/js/Components/MessageTray.js +++ b/assets/js/Components/MessageTray.js @@ -1,48 +1,40 @@ -import React from 'react' +import React, { useEffect} from 'react' import { Alert } from '@instructure/ui-alerts' import { Spinner } from '@instructure/ui-spinner' - import Classes from '../../css/app.css' -class MessageTray extends React.Component { - constructor(props) { - super(props) - } - - componentDidMount() { - this.props.clearMessages() - } +export default function MessageTray ({ messages, hasNewReport, clearMessages, t }) { - render() { - return ( -
- {!this.props.hasNewReport && ( - document.getElementsByClassName(Classes.messagesTray)[0]} - > - {this.props.t('label.content_loading_msg')} - - - )} - {this.props.messages.map((msg, i) => ( - - {this.props.t(msg.message)} - - ))} -
- ) - } -} + useEffect(() => { + clearMessages() + }, []) -export default MessageTray + return ( +
+ {!hasNewReport && ( + document.getElementsByClassName(Classes.messagesTray)[0]} + > + {t('label.content_loading_msg')} + + + )} + {messages.map((msg, i) => ( + + {t(msg.message)} + + ))} +
+ ) +} \ No newline at end of file diff --git a/assets/js/Components/ReportsPage.js b/assets/js/Components/ReportsPage.js index bcd832855..65afcbf42 100644 --- a/assets/js/Components/ReportsPage.js +++ b/assets/js/Components/ReportsPage.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState, useEffect } from 'react' import { View } from '@instructure/ui-view' import { Flex } from '@instructure/ui-flex' import { Text } from '@instructure/ui-text' @@ -12,84 +12,28 @@ import ResolutionsReport from './Reports/ResolutionsReport' import ReportsTable from './Reports/ReportsTable' import IssuesTable from './Reports/IssuesTable' -class ReportsPage extends React.Component { - constructor(props) { - super(props) +export default function ReportsPage({t, report, settings}) { - this.issues = this.processIssues(props.report) + const [reports, setReports] = useState([]) + const [issues, setIssues] = useState([]) - this.state = { - reports: [] - } - } - - componentDidMount() { - if (this.state.reports.length === 0) { - this.getReportHistory() - } - } - - componentDidUpdate() { - this.issues = this.processIssues(this.props.report) - } - - render() { - if (this.state.reports.length === 0) { - return ( - - - - {this.props.t('label.loading_reports')} - - - ) - } else { - return ( - - {this.props.t('label.reports')} - - - - - - - - - - - - - - - - - - ) - } - } - - getReportHistory() { - const api = new Api(this.props.settings) + const getReportHistory = () => { + const api = new Api(settings) api.getReportHistory() .then((responseStr) => responseStr.json()) .then((response) => { - this.setState({reports: response.data}) + setReports(response.data) }) } - processIssues(report) { + const processIssues = (report) => { + let rules = [] for (let issue of report.issues) { const rule = issue.scanRuleId const status = issue.status - + if (!rules[rule]) { rules[rule] = { id: rule, @@ -116,7 +60,53 @@ class ReportsPage extends React.Component { return rules } + useEffect(() => { + if (reports.length === 0) { + getReportHistory() + } + }, []) + + useEffect(() => { + setIssues(processIssues(report)) + }, [report]) + + if (report.length === 0) { + return ( + + + + {t('label.loading_reports')} + + + ) + } else { + return ( + + {t('label.reports')} + + + + + + + + + + + + + + + + + + ) + } -} - -export default ReportsPage \ No newline at end of file +} \ No newline at end of file diff --git a/assets/js/Components/SummaryBar.js b/assets/js/Components/SummaryBar.js index 4f4072180..84ad27a10 100644 --- a/assets/js/Components/SummaryBar.js +++ b/assets/js/Components/SummaryBar.js @@ -1,60 +1,52 @@ -import React from 'react'; +import React from 'react' import { View } from '@instructure/ui-view' import { Text } from '@instructure/ui-text' import { Flex } from '@instructure/ui-flex' import { InlineList } from '@instructure/ui-list' -class SummaryBar extends React.Component { - constructor(props) { - super(props) - } +export default function SummaryBar({ t, report }) { - render() { - const report = this.props.report - return ( - - - - {/* {this.props.t('label.summary')} */} - - - - - - {report.errors} - {this.props.t('label.plural.error')} - - - - - {report.suggestions} - {this.props.t('label.plural.suggestion')} - - - - - {report.contentFixed} - {this.props.t('label.plural.fixed')} - - - - - {report.contentResolved} - {this.props.t('label.manually_resolved')} - - - - - {report.filesReviewed} - {this.props.t('label.files_reviewed')} - - - - - - - ) - } -} - -export default SummaryBar; \ No newline at end of file + return ( + + + + {/* {t('label.summary')} */} + + + + + + {report.errors} + {t('label.plural.error')} + + + + + {report.suggestions} + {t('label.plural.suggestion')} + + + + + {report.contentFixed} + {t('label.plural.fixed')} + + + + + {report.contentResolved} + {t('label.manually_resolved')} + + + + + {report.filesReviewed} + {t('label.files_reviewed')} + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/SummaryForm.js b/assets/js/Components/SummaryForm.js index 25e387381..b5d782305 100644 --- a/assets/js/Components/SummaryForm.js +++ b/assets/js/Components/SummaryForm.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { Heading } from '@instructure/ui-heading' import { Button } from '@instructure/ui-buttons' import { View } from '@instructure/ui-view' @@ -18,180 +18,96 @@ const startOptions = [ 'by_impact' ] -class SummaryForm extends React.Component { - - constructor(props) { - super(props); - - this.state = { - selectFilter: 'easy', - selectRule: '', - selectContentType: '', - selectImpact: '', - } - - this.visualRules = issueRuleIds.filter(rule => this.props.settings.visualRuleIds.includes(rule)) - this.auditoryRules = issueRuleIds.filter(rule => this.props.settings.auditoryRuleIds.includes(rule)) - this.cognitiveRules = issueRuleIds.filter(rule => this.props.settings.cognitiveRuleIds.includes(rule)) - this.motorRules = issueRuleIds.filter(rule => this.props.settings.motorRuleIds.includes(rule)) - - this.handleFilterSelect = this.handleFilterSelect.bind(this) - this.handleRuleSelect = this.handleRuleSelect.bind(this) - this.handleContentTypeSelect = this.handleContentTypeSelect.bind(this) - this.handleImpactSelect = this.handleImpactSelect.bind(this) - this.handleSubmit = this.handleSubmit.bind(this) - } - - render() { - let canSubmit = true - let easyRuleIds = this.props.settings.easyRuleIds - if ('by_issue' === this.state.selectFilter) { - canSubmit = (this.state.selectRule) +export default function SummaryForm({ t, settings, report, handleAppFilters, handleNavigation }) { + const [selectFilter, setSelectFilter] = useState('easy') + const [selectRule, setSelectRule] = useState('') + const [selectContentType, setSelectContentType] = useState('') + const [selectImpact, setSelectImpact] = useState('') + + const visualRules = issueRuleIds.filter(rule => settings.visualRuleIds.includes(rule)) + const auditoryRules = issueRuleIds.filter(rule => settings.auditoryRuleIds.includes(rule)) + const cognitiveRules = issueRuleIds.filter(rule => settings.cognitiveRuleIds.includes(rule)) + const motorRules = issueRuleIds.filter(rule => settings.motorRuleIds.includes(rule)) + const easyRules = issueRuleIds.filter(rule => settings.easyRuleIds.includes(rule)) + + const checkCanSubmit = () => { + let newCanSubmit = true + if (selectFilter === 'by_issue') { + newCanSubmit = selectRule } - if ('by_content' === this.state.selectFilter) { - canSubmit = (this.state.selectContentType) + if (selectFilter === 'by_content') { + newCanSubmit = selectContentType } - if ('by_impact' === this.state.selectFilter) { - canSubmit = (this.state.selectImpact) + if (selectFilter === 'by_impact') { + newCanSubmit = selectImpact } - - this.easyRules = issueRuleIds.filter(rule => easyRuleIds.includes(rule)) - - - - return ( - - {this.props.t('form.summary.heading')} - {/* {this.props.t('form.summary.description')} */} - - - {startOptions.map((key) => )} - - - {('by_issue' === this.state.selectFilter) && - - - {this.renderIssueOptions()} - - - } - - {('by_content' === this.state.selectFilter) && - - - {this.renderContentTypeOptions()} - - - } - - {('by_impact' === this.state.selectFilter) && - - - {this.renderImpactOptions()} - - - } - - - {this.renderIssueCount()} - - - - - - - ) + return newCanSubmit; } + const canSubmit = checkCanSubmit() - handleFilterSelect(e, val) - { - this.setState({selectFilter: val}) + const handleFilterSelect = (e, val) => { + setSelectFilter(val) } - handleRuleSelect(e, val) - { - this.setState({selectRule: val.id}) + const handleRuleSelect = (e, val) => { + setSelectRule(val.id) } - handleContentTypeSelect(e, val) - { - this.setState({ selectContentType: val.id }) + const handleContentTypeSelect = (e, val) => { + setSelectContentType(val.id) } - handleImpactSelect(e, val) - { - this.setState({ selectImpact: val.id }) + const handleImpactSelect = (e, val) => { + setSelectImpact(val.id) } - handleSubmit(e) - { - const { selectFilter, selectRule, selectContentType, selectImpact} = this.state + const handleSubmit = (e) => { let filters = {} switch (selectFilter) { case 'easy': filters = {easyIssues: true} - break + break case 'errors_only': filters = {issueTypes: ['error']} - break + break case 'active': filters = {issueStatus: ['active']} - break + break case 'by_issue': filters = {issueTitles: [selectRule]} - break + break case 'by_content': filters = {contentTypes: [selectContentType]} - break + break case 'by_impact': filters = {issueImpacts: [selectImpact]} - break + break } - this.props.handleAppFilters(filters); - this.props.handleNavigation('content'); + handleAppFilters(filters) + handleNavigation('content') } - renderIssueOptions() { + const renderIssueOptions = () => { let options = {} let out = [ -- ] - for (const issue of this.props.report.issues) { + for (const issue of report.issues) { options[issue.scanRuleId] = issue.type } for (let ruleId of Object.keys(options)) { - out.push({this.props.t(`rule.label.${ruleId}`)}) + out.push({t(`rule.label.${ruleId}`)}) } return out } - renderContentTypeOptions() { - let types = this.props.settings.contentTypes + const renderContentTypeOptions = () => { + let types = settings.contentTypes let out = [ -- ] @@ -199,51 +115,51 @@ class SummaryForm extends React.Component { types.sort() for (let type of types) { - out.push({this.props.t(`content.plural.${type}`)}) + out.push({t(`content.plural.${type}`)}) } return out } - renderImpactOptions() { + const renderImpactOptions = () => { let impacts = ['visual', 'auditory', 'cognitive', 'motor'] let out = [ -- ] for (let impact of impacts) { - out.push({this.props.t(`label.filter.${impact}`)}) + out.push({t(`label.filter.${impact}`)}) } return out } - renderIssueCount() { + const renderIssueCount = () => { let values = ['-', '-'] - switch (this.state.selectFilter) { + switch (selectFilter) { case 'easy': - values = this.getEasyCount() + values = getEasyCount() break case 'errors_only': - values = this.getErrorCount() + values = getErrorCount() break case 'active': - values = this.getActiveIssueCount() + values = getActiveIssueCount() break case 'by_issue': - if (this.state.selectRule) { - values = this.getIssueTypeCount() + if (selectRule) { + values = getIssueTypeCount() } break case 'by_content': - if (this.state.selectContentType) { - values = this.getContentTypeCount() + if (selectContentType) { + values = getContentTypeCount() } break case 'by_impact': - if (this.state.selectImpact) { - values = this.getImpactCount() + if (selectImpact) { + values = getImpactCount() } break } @@ -253,19 +169,18 @@ class SummaryForm extends React.Component { {values[0] && - {values[0]} {this.props.t('label.plural.error')} + {values[0]} {t('label.plural.error')} } {values[1] && - {values[1]} {this.props.t('label.plural.suggestion')} + {values[1]} {t('label.plural.suggestion')} } ) } - getEasyCount() { - const report = this.props.report + const getEasyCount = () => { let errors = 0 let suggestions = 0 @@ -274,7 +189,7 @@ class SummaryForm extends React.Component { continue } - if (this.easyRules.includes(issue.scanRuleId)) { + if (easyRules.includes(issue.scanRuleId)) { if ('error' === issue.type) { errors++ } @@ -287,8 +202,7 @@ class SummaryForm extends React.Component { return [errors, suggestions] } - getErrorCount() { - const report = this.props.report + const getErrorCount = () => { let errors = 0 for (const issue of report.issues) { @@ -303,8 +217,7 @@ class SummaryForm extends React.Component { return [errors, 0] } - getActiveIssueCount() { - const report = this.props.report + const getActiveIssueCount = () => { let errors = 0 let suggestions = 0 @@ -323,8 +236,7 @@ class SummaryForm extends React.Component { return [errors, suggestions] } - getIssueTypeCount() { - const report = this.props.report + const getIssueTypeCount = () => { let errors = 0 let suggestions = 0 @@ -332,7 +244,7 @@ class SummaryForm extends React.Component { if (issue.status) { continue } - if (this.state.selectRule === issue.scanRuleId) { + if (selectRule === issue.scanRuleId) { if ('error' === issue.type) { errors++ } @@ -345,8 +257,7 @@ class SummaryForm extends React.Component { return [errors, suggestions] } - getContentTypeCount() { - const report = this.props.report + const getContentTypeCount = () => { let errors = 0 let suggestions = 0 @@ -356,7 +267,7 @@ class SummaryForm extends React.Component { } const contentItem = Object.assign({}, report.contentItems[issue.contentItemId]) - if (this.state.selectContentType === contentItem.contentType) { + if (selectContentType === contentItem.contentType) { if ('error' === issue.type) { errors++ } @@ -369,8 +280,7 @@ class SummaryForm extends React.Component { return [errors, suggestions] } - getImpactCount() { - const report = this.props.report + const getImpactCount = () => { let errors = 0 let suggestions = 0 @@ -379,10 +289,10 @@ class SummaryForm extends React.Component { continue } - if ((this.state.selectImpact === 'visual' && this.visualRules.includes(issue.scanRuleId)) - || (this.state.selectImpact === 'auditory' && this.auditoryRules.includes(issue.scanRuleId)) - || (this.state.selectImpact === 'cognitive' && this.cognitiveRules.includes(issue.scanRuleId)) - || (this.state.selectImpact === 'motor' && this.motorRules.includes(issue.scanRuleId)) + if ((selectImpact === 'visual' && visualRules.includes(issue.scanRuleId)) + || (selectImpact === 'auditory' && auditoryRules.includes(issue.scanRuleId)) + || (selectImpact === 'cognitive' && cognitiveRules.includes(issue.scanRuleId)) + || (selectImpact === 'motor' && motorRules.includes(issue.scanRuleId)) ) { if ('error' === issue.type) { errors++ @@ -395,6 +305,66 @@ class SummaryForm extends React.Component { return [errors, suggestions] } -} -export default SummaryForm + return ( + + {t('form.summary.heading')} + + + {startOptions.map((key) => )} + + + {('by_issue' === selectFilter) && + + + {renderIssueOptions()} + + + } + + {('by_content' === selectFilter) && + + + {renderContentTypeOptions()} + + + } + + {('by_impact' === selectFilter) && + + + {renderImpactOptions()} + + + } + + + {renderIssueCount()} + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/SummaryPage.js b/assets/js/Components/SummaryPage.js index 621d8041a..824e44e1e 100644 --- a/assets/js/Components/SummaryPage.js +++ b/assets/js/Components/SummaryPage.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { Table } from '@instructure/ui-table' import { Text } from '@instructure/ui-text' import { View } from '@instructure/ui-view' @@ -11,31 +11,16 @@ import Classes from '../../css/theme-overrides.css' import SummaryForm from './SummaryForm' -class SummaryPage extends React.Component { +export default function SummaryPage({ report, t, handleAppFilters, handleNavigation, settings }) { - constructor(props) { - super(props); - - this.state = { - showMoreSummary: false - } - - //this.handleIssueTypeLink = this.handleIssueTypeLink.bind(this) - //this.handleShowMore = this.handleShowMore.bind(this) - } - - processReportData(report) { + const processReportData = () => { let issueResults = { - error: {}, - suggestion: {} - }; - - this.contentResults = {}; - this.issueResults = { error: [], suggestion: [] }; + let contentResults = {}; + if (report && report.issues) { for (let issueId in report.issues) { const issue = report.issues[issueId]; @@ -46,13 +31,13 @@ class SummaryPage extends React.Component { } if (contentItem && contentItem.contentType) { - if (!this.contentResults[contentItem.contentType]) { - this.contentResults[contentItem.contentType] = { + if (!contentResults[contentItem.contentType]) { + contentResults[contentItem.contentType] = { error: 0, suggestion: 0 }; } - this.contentResults[contentItem.contentType][issue.type]++; + contentResults[contentItem.contentType][issue.type]++; } if(!issueResults[issue.type].hasOwnProperty(issue.scanRuleId)) { @@ -64,66 +49,29 @@ class SummaryPage extends React.Component { for (const type in issueResults) { for (const ruleId in issueResults[type]) { - this.issueResults[type].push([ruleId, issueResults[type][ruleId]]); + issueResults[type].push([ruleId, issueResults[type][ruleId]]); } } - this.issueResults.error.sort((a, b) => (a[1] > b[1]) ? -1 : 1 ); - this.issueResults.suggestion.sort((a, b) => (a[1] > b[1]) ? -1 : 1); + issueResults.error.sort((a, b) => (a[1] > b[1]) ? -1 : 1 ); + issueResults.suggestion.sort((a, b) => (a[1] > b[1]) ? -1 : 1); } + + return { issueResults, contentResults } } - render() { - const report = this.props.report - const infoLabel = (this.state.showMoreSummary) ? 'label.less_info' : 'label.more_info' + const handleIssueTitleLink = (ruleId) => { + handleAppFilters({issueTitles: [ruleId]}); + handleNavigation('content'); + } - return ( - - {/* {this.props.t('label.summary')} */} - - - - - - - - - - - - {this.renderSummaryTables()} - - - - - - - - - ) + const handleMetricClick = (val) => { + handleAppFilters({issueTypes: [val] }) + handleNavigation('content') } - renderSummaryTables() { - const report = this.props.report; - this.processReportData(report) + const renderSummaryTables = () => { + const { issueResults, contentResults } = processReportData() const maxRows = 3 return ( @@ -131,11 +79,11 @@ class SummaryPage extends React.Component { - {`${report.errors} ${this.props.t(`label.plural.error`)}`} + {`${report.errors} ${t(`label.plural.error`)}`} - {this.props.t(`label.most_common`) + ' ' + this.props.t(`label.plural.error`)} + {t(`label.most_common`) + ' ' + t(`label.plural.error`)} - {this.issueResults['error'].map((val, ind) => { + {issueResults['error'].map((val, ind) => { if (ind >= maxRows) { return } return ( - this.handleIssueTitleLink(val[0])}> + handleIssueTitleLink(val[0])}> {val[1]} - {this.props.t(`rule.label.${val[0]}`)} + {t(`rule.label.${val[0]}`)} - this.handleIssueTitleLink(val[0])}> + handleIssueTitleLink(val[0])}> @@ -180,11 +128,11 @@ class SummaryPage extends React.Component { - {`${report.suggestions} ${this.props.t(`label.plural.suggestion`)}`} + {`${report.suggestions} ${t(`label.plural.suggestion`)}`}
- {this.props.t(`label.most_common`) + ' ' + this.props.t(`label.plural.suggestion`)} + {t(`label.most_common`) + ' ' + t(`label.plural.suggestion`)} - {this.issueResults['suggestion'].map((val, ind) => { + {issueResults['suggestion'].map((val, ind) => { if (ind >= maxRows) { return } return ( - this.handleIssueTitleLink(val[0])}> + handleIssueTitleLink(val[0])}> {val[1]} - {this.props.t(`rule.label.${val[0]}`)} + {t(`rule.label.${val[0]}`)} @@ -228,24 +176,46 @@ class SummaryPage extends React.Component { ) } - // handleShowMore(e) { - // this.setState({ showMoreSummary: !this.state.showMoreSummary }) - // } - - // handleIssueTypeLink(contentType, issueType) { - // this.props.handleAppFilters({contentTypes: [contentType], issueTypes: [issueType]}); - // this.props.handleNavigation('content'); - // } - - handleIssueTitleLink(ruleId) { - this.props.handleAppFilters({issueTitles: [ruleId]}); - this.props.handleNavigation('content'); - } - - handleMetricClick(val) { - this.props.handleAppFilters({issueTypes: [val] }) - this.props.handleNavigation('content') - } -} - -export default SummaryPage; + return ( + + {/* {t('label.summary')} */} + + + + + + + + + + + + { renderSummaryTables() } + + + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Components/UfixitModal.js b/assets/js/Components/UfixitModal.js index cfa1e03f9..1aa068237 100644 --- a/assets/js/Components/UfixitModal.js +++ b/assets/js/Components/UfixitModal.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Modal } from '@instructure/ui-modal' import { Heading } from '@instructure/ui-heading' import { Button } from '@instructure/ui-buttons' @@ -24,283 +24,107 @@ import * as Html from '../Services/Html' import Pretty from 'pretty' -class UfixitModal extends React.Component { - - constructor(props) { - super(props); - - this.state = { - windowContents: 'preview', - expandExample: false, - } - - this.modalMessages = [] - - this.handleWindowToggle = this.handleWindowToggle.bind(this) - this.addMessage = this.addMessage.bind(this) - this.clearMessages = this.clearMessages.bind(this) - this.handleIssueSave = this.handleIssueSave.bind(this) - this.handleIssueResolve = this.handleIssueResolve.bind(this) - this.handleOpenContent = this.handleOpenContent.bind(this) - this.handleExampleToggle = this.handleExampleToggle.bind(this) - this.handleManualScan = this.handleManualScan.bind(this) - } - - findActiveIndex() { - if (this.props.filteredRows && this.props.activeIssue) { - for (const i in this.props.filteredRows) { - let issue = this.props.filteredRows[i] - if (issue.issue.id === this.props.activeIssue.id) { +export default function UfixitModal({ + t, + settings, + open, + activeIssue, + activeIndex, + activeContentItem, + filteredRows, + handleCloseButton, + handleActiveIssue, + handleIssueSave +}) { + + const [windowContents, setWindowContents] = useState('preview') + const [expandExample, setExpandExample] = useState(false) + const [showExample, setShowExample] = useState(false) + const [pending, setPending] = useState(false) + const [currentIndex, setCurrentIndex] = useState(0) + const [modalMessages, setModalMessages] = useState([]) + const [code, setCode] = useState('') + let UfixitForm = returnIssueForm(activeIssue) + + const findActiveIndex = () => { + if (filteredRows && activeIssue) { + for (const i in filteredRows) { + let issue = filteredRows[i] + if (issue.issue.id === activeIssue.id) { return Number(i) } } } - return 0; } // Handler for the previous and next buttons on the modal // Will wrap around if the index goes out of bounds - handleIssueChange(newIndex) { + const handleIssueChange = (newIndex) => { if (newIndex < 0) { - newIndex = this.props.filteredRows.length - 1 + newIndex = filteredRows.length - 1 } - if (newIndex > (this.props.filteredRows.length - 1)) { + if (newIndex > (filteredRows.length - 1)) { newIndex = 0 } - this.clearMessages() - this.props.handleActiveIssue(this.props.filteredRows[newIndex].issue, newIndex) - } - - handleWindowToggle(val) { - this.setState({windowContents: val}) + clearMessages() + handleActiveIssue(filteredRows[newIndex].issue, newIndex) } - handleOpenContent(e) { - const contentItem = this.props.activeContentItem - window.open(contentItem.url, '_blank', 'noopener,noreferrer') + const handleWindowToggle = (val) => { + setWindowContents(val) } - render() { - const { activeIssue, activeContentItem } = this.props - - const pending = (this.props.activeIssue && (this.props.activeIssue.pending == '1')) - - let activeIndex = this.findActiveIndex(); - const UfixitForm = returnIssueForm(activeIssue) - - let showExample = false - if (!this.props.t(`rule.example.${activeIssue.scanRuleId}`).includes('rule.example')) { - showExample = true - } - - let code = this.prepareCode(activeIssue) - - return ( - - {this.props.open && - - - - - {this.props.t(`rule.label.${activeIssue.scanRuleId}`)} - - - - - - - - - - - - {ReactHtmlParser(this.props.t(`rule.desc.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - - - {showExample && - - - {ReactHtmlParser(this.props.t(`rule.example.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} - - - } - - - - - - - {('module' !== activeContentItem.contentType) && - - {this.props.t('label.manual_resolution')} - {this.props.t('label.resolved_description')} - - {('2' == activeIssue.pending) ? - - : - - } - - - } - - - - - - {('preview' === this.state.windowContents) ? - {this.props.t('label.preview')} - : - this.handleWindowToggle('preview')}> - {this.props.t('label.preview')} - } - - - {('html' === this.state.windowContents) ? - {this.props.t('label.view_source')} - : - this.handleWindowToggle('html')}> - {this.props.t('label.view_source')} - } - - - - {('preview' === this.state.windowContents) && - - - } - {('html' === this.state.windowContents) && - - } - - - - {/* {this.props.t('label.source')} */} - {activeContentItem && - - {activeContentItem.contentType} - } iconPlacement="end"> - {activeContentItem.title} - - - } - - - - - - - - - - - - {this.props.t('label.issue')} {(activeIndex + 1)} {this.props.t('label.of')} {this.props.filteredRows.length} - - {activeIssue.status && !activeIssue.pending && - - {('1' == activeIssue.status) && - - - {this.props.t('label.fixed')} - - } - {('2' == activeIssue.status) && - - - {this.props.t('label.resolved')} - - } - - } - - - - - - - - - - - - } - ) + const handleOpenContent = (e) => { + const contentItem = activeContentItem + window.open(contentItem.url, '_blank', 'noopener,noreferrer') } - prepareCode(activeIssue) { + const prepareCode = (activeIssue) => { let sourceCode = (activeIssue.newHtml) ? activeIssue.newHtml : activeIssue.sourceHtml - let code = sourceCode + let tempCode = sourceCode if (sourceCode.length === 0 || sourceCode.length > 3000) { - code = 'Not Available' + tempCode = 'Not Available' } else { let element = Html.toElement(sourceCode) if(element && element.tagName === 'TH') { - code = activeIssue.previewHtml + tempCode = activeIssue.previewHtml } } - return Pretty(code) + return Pretty(tempCode) } - - handleIssueResolve() { - let activeIssue = Object.assign({}, this.props.activeIssue) - if (activeIssue.pending) { + const handleIssueResolve = () => { + let tempIssue = Object.assign({}, activeIssue) + if (tempIssue.pending) { return } - if (activeIssue.status) { - activeIssue.status = false - activeIssue.newHtml = Html.toString(Html.removeClass(activeIssue.sourceHtml, 'phpally-ignore')) + if (tempIssue.status) { + tempIssue.status = false + tempIssue.newHtml = Html.toString(Html.removeClass(tempIssue.sourceHtml, 'phpally-ignore')) } else { - activeIssue.status = 2 - activeIssue.newHtml = Html.toString(Html.addClass(activeIssue.sourceHtml, 'phpally-ignore')) + tempIssue.status = 2 + tempIssue.newHtml = Html.toString(Html.addClass(tempIssue.sourceHtml, 'phpally-ignore')) } - - let api = new Api(this.props.settings) - api.resolveIssue(activeIssue) + + let api = new Api(settings) + api.resolveIssue(tempIssue) .then((responseStr) => responseStr.json()) .then((response) => { // set messages - response.messages.forEach((msg) => this.addMessage(msg)) + response.messages.forEach((msg) => addMessage(msg)) if (response.data.issue) { - const newIssue = { ...activeIssue, ...response.data.issue } + const newIssue = { ...tempIssue, ...response.data.issue } const newReport = response.data.report // update activeIssue newIssue.pending = false - newIssue.recentlyResolved = !!activeIssue.status + newIssue.recentlyResolved = !!tempIssue.status newIssue.sourceHtml = newIssue.newHtml newIssue.newHtml = '' // Get updated report @@ -308,44 +132,44 @@ class UfixitModal extends React.Component { .then((responseStr) => responseStr.json()) .then((res) => { // update activeIssue - this.props.handleActiveIssue(newIssue) + handleActiveIssue(newIssue) - this.props.handleIssueSave(newIssue, res.data) + handleIssueSave(newIssue, res.data) }) } else { - activeIssue.pending = false - this.props.handleActiveIssue(activeIssue) + tempIssue.pending = false + handleActiveIssue(tempIssue) } }) - activeIssue.pending = 2 - this.props.handleActiveIssue(activeIssue) + tempIssue.pending = 2 + handleActiveIssue(tempIssue) } - handleIssueSave(issue) { + const handleSingleIssueSave = (issue) => { // send issue obj to PHP - let api = new Api(this.props.settings) + let api = new Api(settings) api.saveIssue(issue) .then((responseStr) => responseStr.json()) .then((response) => { // specific to a failed rescan of the HTML if (response.data.failed) { - response.messages.forEach((msg) => this.addMessage(msg)) + response.messages.forEach((msg) => addMessage(msg)) if (Array.isArray(response.data.issues)) { response.data.issues.forEach((issue) => { - this.addMessage({ + addMessage({ severity: 'error', - message: this.props.t(`form.error.${issue.ruleId}`) + message: t(`form.error.${issue.ruleId}`) }) }) } if (Array.isArray(response.data.errors)) { response.data.errors.forEach((error) => { - this.addMessage({ + addMessage({ severity: 'error', message: error }) @@ -354,11 +178,11 @@ class UfixitModal extends React.Component { // update activeIssue issue.pending = false - this.props.handleActiveIssue(issue) + handleActiveIssue(issue) } else { // set messages - response.messages.forEach((msg) => this.addMessage(msg)) + response.messages.forEach((msg) => addMessage(msg)) if (response.data.issue) { const newIssue = {...issue, ...response.data.issue} @@ -370,33 +194,31 @@ class UfixitModal extends React.Component { .then((responseStr) => responseStr.json()) .then((res) => { // update activeIssue - this.props.handleActiveIssue(newIssue) - - this.props.handleIssueSave(newIssue, res.data) + handleActiveIssue(newIssue) + handleIssueSave(newIssue, res.data) }) } else { issue.pending = false - this.props.handleActiveIssue(issue) + handleActiveIssue(issue) } } }) // update activeIssue issue.pending = 1 - this.props.handleActiveIssue(issue) + handleActiveIssue(issue) } - - handleManualScan(issue) { - let api = new Api(this.props.settings) + const handleManualScan = (issue) => { + let api = new Api(settings) api.scanIssue(issue.id) .then((response) => response.json()) .then((data) => { if (data.messages) { data.messages.forEach((msg) => { if (msg.visible) { - this.addMessage(msg); + addMessage(msg); } }); } @@ -405,33 +227,629 @@ class UfixitModal extends React.Component { newIssue.pending = false newIssue.recentlyUpdated = true - this.props.handleIssueSave(newIssue, data.data.report) + handleIssueSave(newIssue, data.data.report) // update activeIssue - this.props.handleActiveIssue(newIssue) + handleActiveIssue(newIssue) } else { issue.pending = false - this.props.handleActiveIssue(issue) + handleActiveIssue(issue) } }) // update activeIssue issue.pending = 1 - this.props.handleActiveIssue(issue) - } - - handleExampleToggle() { - this.setState({expandExample: !this.state.expandExample}) + handleActiveIssue(issue) } - addMessage = (msg) => { - this.modalMessages.push(msg); + const handleExampleToggle = () => { + setExpandExample(!expandExample) } - clearMessages() { - this.modalMessages = []; + const addMessage = (msg) => { + setModalMessages([...modalMessages, msg]) } + + const clearMessages = () => { + setModalMessages([]) + } + + useEffect(() => { + console.info('UfixitModal loaded') + console.info(JSON.stringify(activeIssue)) + + setPending(activeIssue && (activeIssue.pending == '1')) + UfixitForm = returnIssueForm(activeIssue) + + if (!t(`rule.example.${activeIssue.scanRuleId}`).includes('rule.example')) { + setShowExample(true) + } + else { + setShowExample(false) + } + + setCurrentIndex(findActiveIndex()) + setCode(prepareCode(activeIssue)) + + }, [activeIssue, activeContentItem]) + + return ( + + {open && + + + + + {t(`rule.label.${activeIssue.scanRuleId}`)} + + + + + + + + + + + + {ReactHtmlParser(t(`rule.desc.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + {showExample && + + + {ReactHtmlParser(t(`rule.example.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, settings) })} + + + } + + + + + {UfixitForm && + } + + {('module' !== activeContentItem.contentType) && + + {t('label.manual_resolution')} + {t('label.resolved_description')} + + {('2' == activeIssue.pending) ? + + : + + } + + + } + + + + + + {('preview' === windowContents) ? + {t('label.preview')} + : + handleWindowToggle('preview')}> + {t('label.preview')} + } + + + {('html' === windowContents) ? + {t('label.view_source')} + : + handleWindowToggle('html')}> + {t('label.view_source')} + } + + + + {('preview' === windowContents) && + + + } + {('html' === windowContents) && + + } + + + + {/* {t('label.source')} */} + {activeContentItem && + + {activeContentItem.contentType} + } iconPlacement="end"> + {activeContentItem.title} + + + } + + + + + + + + + + + + {t('label.issue')} {(currentIndex + 1)} {t('label.of')} {filteredRows.length} + + {activeIssue.status && !activeIssue.pending && + + {('1' == activeIssue.status) && + + + {t('label.fixed')} + + } + {('2' == activeIssue.status) && + + + {t('label.resolved')} + + } + + } + + + + + + + + + + + + } + + ) } -export default UfixitModal; + + + + +// class UfixitModal extends React.Component { + +// constructor(props) { +// super(props); + +// this.state = { +// windowContents: 'preview', +// expandExample: false, +// } + +// this.modalMessages = [] + +// this.handleWindowToggle = this.handleWindowToggle.bind(this) +// this.addMessage = this.addMessage.bind(this) +// this.clearMessages = this.clearMessages.bind(this) +// this.handleIssueSave = this.handleIssueSave.bind(this) +// this.handleIssueResolve = this.handleIssueResolve.bind(this) +// this.handleOpenContent = this.handleOpenContent.bind(this) +// this.handleExampleToggle = this.handleExampleToggle.bind(this) +// this.handleManualScan = this.handleManualScan.bind(this) +// } + +// findActiveIndex() { +// if (this.props.filteredRows && this.props.activeIssue) { +// for (const i in this.props.filteredRows) { +// let issue = this.props.filteredRows[i] +// if (issue.issue.id === this.props.activeIssue.id) { +// return Number(i) +// } +// } +// } + +// return 0; +// } + +// // Handler for the previous and next buttons on the modal +// // Will wrap around if the index goes out of bounds +// handleIssueChange(newIndex) { +// if (newIndex < 0) { +// newIndex = this.props.filteredRows.length - 1 +// } +// if (newIndex > (this.props.filteredRows.length - 1)) { +// newIndex = 0 +// } +// this.clearMessages() +// this.props.handleActiveIssue(this.props.filteredRows[newIndex].issue, newIndex) +// } + +// handleWindowToggle(val) { +// this.setState({windowContents: val}) +// } + +// handleOpenContent(e) { +// const contentItem = this.props.activeContentItem +// window.open(contentItem.url, '_blank', 'noopener,noreferrer') +// } + +// render() { +// const { activeIssue, activeContentItem } = this.props + +// const pending = (this.props.activeIssue && (this.props.activeIssue.pending == '1')) + +// let activeIndex = this.findActiveIndex(); +// const UfixitForm = returnIssueForm(activeIssue) + +// let showExample = false +// if (!this.props.t(`rule.example.${activeIssue.scanRuleId}`).includes('rule.example')) { +// showExample = true +// } + +// let code = this.prepareCode(activeIssue) + +// return ( +// +// {this.props.open && +// +// +// +// +// {this.props.t(`rule.label.${activeIssue.scanRuleId}`)} +// +// +// +// +// +// +// +// +// +// +// +// {ReactHtmlParser(this.props.t(`rule.desc.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} +// +// +// {showExample && +// +// +// {ReactHtmlParser(this.props.t(`rule.example.${activeIssue.scanRuleId}`), { preprocessNodes: (nodes) => Html.processStaticHtml(nodes, this.props.settings) })} +// +// +// } +// +// +// +// +// +// +// {('module' !== activeContentItem.contentType) && +// +// {this.props.t('label.manual_resolution')} +// {this.props.t('label.resolved_description')} +// +// {('2' == activeIssue.pending) ? +// +// : +// +// } +// +// +// } +// +// +// +// +// +// {('preview' === this.state.windowContents) ? +// {this.props.t('label.preview')} +// : +// this.handleWindowToggle('preview')}> +// {this.props.t('label.preview')} +// } +// +// +// {('html' === this.state.windowContents) ? +// {this.props.t('label.view_source')} +// : +// this.handleWindowToggle('html')}> +// {this.props.t('label.view_source')} +// } +// +// +// +// {('preview' === this.state.windowContents) && +// +// +// } +// {('html' === this.state.windowContents) && +// +// } +// +// +// +// {/* {this.props.t('label.source')} */} +// {activeContentItem && +// +// {activeContentItem.contentType} +// } iconPlacement="end"> +// {activeContentItem.title} +// +// +// } +// +// +// +// + +// +// +// +// +// +// +// {this.props.t('label.issue')} {(activeIndex + 1)} {this.props.t('label.of')} {this.props.filteredRows.length} +// +// {activeIssue.status && !activeIssue.pending && +// +// {('1' == activeIssue.status) && +// +// +// {this.props.t('label.fixed')} +// +// } +// {('2' == activeIssue.status) && +// +// +// {this.props.t('label.resolved')} +// +// } +// +// } +// +// +// +// +// +// +// +// +// +// +// +// } +// ) +// } + +// prepareCode(activeIssue) { +// let sourceCode = (activeIssue.newHtml) ? activeIssue.newHtml : activeIssue.sourceHtml +// let code = sourceCode + +// if (sourceCode.length === 0 || sourceCode.length > 3000) { +// code = 'Not Available' +// } else { +// let element = Html.toElement(sourceCode) + +// if(element && element.tagName === 'TH') { +// code = activeIssue.previewHtml +// } +// } +// return Pretty(code) +// } + + +// handleIssueResolve() { +// let activeIssue = Object.assign({}, this.props.activeIssue) +// if (activeIssue.pending) { +// return +// } + +// if (activeIssue.status) { +// activeIssue.status = false +// activeIssue.newHtml = Html.toString(Html.removeClass(activeIssue.sourceHtml, 'phpally-ignore')) +// } +// else { +// activeIssue.status = 2 +// activeIssue.newHtml = Html.toString(Html.addClass(activeIssue.sourceHtml, 'phpally-ignore')) +// } + +// let api = new Api(this.props.settings) +// api.resolveIssue(activeIssue) +// .then((responseStr) => responseStr.json()) +// .then((response) => { +// // set messages +// response.messages.forEach((msg) => this.addMessage(msg)) + +// if (response.data.issue) { +// const newIssue = { ...activeIssue, ...response.data.issue } +// const newReport = response.data.report + +// // update activeIssue +// newIssue.pending = false +// newIssue.recentlyResolved = !!activeIssue.status +// newIssue.sourceHtml = newIssue.newHtml +// newIssue.newHtml = '' +// // Get updated report +// api.scanContent(newIssue.contentItemId) +// .then((responseStr) => responseStr.json()) +// .then((res) => { +// // update activeIssue +// this.props.handleActiveIssue(newIssue) + +// this.props.handleIssueSave(newIssue, res.data) +// }) +// } +// else { +// activeIssue.pending = false +// this.props.handleActiveIssue(activeIssue) +// } +// }) + +// activeIssue.pending = 2 +// this.props.handleActiveIssue(activeIssue) +// } + +// handleIssueSave(issue) { +// // send issue obj to PHP +// let api = new Api(this.props.settings) + +// api.saveIssue(issue) +// .then((responseStr) => responseStr.json()) +// .then((response) => { +// // specific to a failed rescan of the HTML +// if (response.data.failed) { +// response.messages.forEach((msg) => this.addMessage(msg)) + +// if (Array.isArray(response.data.issues)) { +// response.data.issues.forEach((issue) => { +// this.addMessage({ +// severity: 'error', +// message: this.props.t(`form.error.${issue.ruleId}`) +// }) +// }) +// } + +// if (Array.isArray(response.data.errors)) { +// response.data.errors.forEach((error) => { +// this.addMessage({ +// severity: 'error', +// message: error +// }) +// }) +// } + +// // update activeIssue +// issue.pending = false +// this.props.handleActiveIssue(issue) +// } +// else { +// // set messages +// response.messages.forEach((msg) => this.addMessage(msg)) + +// if (response.data.issue) { +// const newIssue = {...issue, ...response.data.issue} +// newIssue.pending = false +// newIssue.recentlyUpdated = true + +// // Get updated report +// api.scanContent(newIssue.contentItemId) +// .then((responseStr) => responseStr.json()) +// .then((res) => { +// // update activeIssue +// this.props.handleActiveIssue(newIssue) + +// this.props.handleIssueSave(newIssue, res.data) +// }) +// } +// else { +// issue.pending = false +// this.props.handleActiveIssue(issue) +// } +// } +// }) + +// // update activeIssue +// issue.pending = 1 +// this.props.handleActiveIssue(issue) +// } + + +// handleManualScan(issue) { +// let api = new Api(this.props.settings) +// api.scanIssue(issue.id) +// .then((response) => response.json()) +// .then((data) => { +// if (data.messages) { +// data.messages.forEach((msg) => { +// if (msg.visible) { +// this.addMessage(msg); +// } +// }); +// } +// if (data.data.issue) { +// const newIssue = { ...issue, ...data.data.issue } +// newIssue.pending = false +// newIssue.recentlyUpdated = true + +// this.props.handleIssueSave(newIssue, data.data.report) + +// // update activeIssue +// this.props.handleActiveIssue(newIssue) +// } +// else { +// issue.pending = false +// this.props.handleActiveIssue(issue) +// } +// }) + +// // update activeIssue +// issue.pending = 1 +// this.props.handleActiveIssue(issue) +// } + +// handleExampleToggle() { +// this.setState({expandExample: !this.state.expandExample}) +// } + +// addMessage = (msg) => { +// this.modalMessages.push(msg); +// } + +// clearMessages() { +// this.modalMessages = []; +// } +// } + +// export default UfixitModal; diff --git a/assets/js/Components/WelcomePage.js b/assets/js/Components/WelcomePage.js index 4adb7ffff..22b730706 100644 --- a/assets/js/Components/WelcomePage.js +++ b/assets/js/Components/WelcomePage.js @@ -6,36 +6,11 @@ import { Checkbox } from '@instructure/ui-checkbox' import AboutPage from './AboutPage' import Api from '../Services/Api' -class WelcomePage extends React.Component { - constructor(props) { - super(props) +export default function WelcomePage({ t, settings, setSettings, hasNewReport, handleNavigation }) { - this.handleSkipWelcomeMessage = this.handleSkipWelcomeMessage.bind(this) - } - - render() { - return ( - - - {this.props.t('about.title')} - - - - - - - - - - ) - } - - handleSkipWelcomeMessage(event) { - let api = new Api(this.props.settings) - let user = this.props.settings.user + const handleSkipWelcomeMessage = (event) => { + let api = new Api(settings) + let user = settings.user if (event.target.checked) { user.roles = ['ROLE_ADVANCED_USER'] @@ -47,10 +22,27 @@ class WelcomePage extends React.Component { api.updateUser(user) .then((response) => response.json()) .then((data) => { - this.props.settings.user = data + let newSettings = [...settings] + newSettings.user = data + setSettings(newSettings) }) - } -} -export default WelcomePage; \ No newline at end of file + return ( + + + {t('about.title')} + + + + + + + + + + ) +} \ No newline at end of file diff --git a/assets/js/Services/Ufixit.js b/assets/js/Services/Ufixit.js index 5bef00318..5647ad213 100644 --- a/assets/js/Services/Ufixit.js +++ b/assets/js/Services/Ufixit.js @@ -8,8 +8,12 @@ import TableHeaders from '../Components/Forms/TableHeaders' import Video from '../Components/Forms/Video' import LinkForm from '../Components/Forms/LinkForm' import EmphasisForm from '../Components/Forms/EmphasisForm' +import LabelForm from '../Components/Forms/LabelForm' +import QuoteForm from '../Components/Forms/QuoteForm' +import StyleMisuseForm from '../Components/Forms/StyleMisuseForm' const UfixitForms = { + // phpAlly rules AnchorMustContainText: AnchorText, AnchorSuspiciousLinkText: AnchorText, BrokenLink: LinkForm, @@ -29,6 +33,16 @@ const UfixitForms = { VideoCaptionsMatchCourseLanguage: Video, VideosEmbeddedOrLinkedNeedCaptions: Video, VideosHaveAutoGeneratedCaptions: Video, + + // Equal Access Rules + img_alt_misuse: AltText, + aria_application_labelled: LabelForm, + aria_application_label_unique: LabelForm, + text_contrast_sufficient: ContrastForm, + text_block_heading: HeadingStyleForm, + heading_content_exists: HeadingEmptyForm, + // text_quoted_correctly: QuoteForm, + style_color_misuse: StyleMisuseForm, } export function returnIssueForm(activeIssue) { diff --git a/assets/js/getInitialData.js b/assets/js/getInitialData.js index 107f76fb2..830be3fba 100644 --- a/assets/js/getInitialData.js +++ b/assets/js/getInitialData.js @@ -16,7 +16,7 @@ export default function getInitialData() { data = JSON.parse(settingsElement.textContent) if (Object.keys(data).length > 0) { - console.log('Data was found and loaded!') + console.info('UDOIT initial LMS data was found and loaded!') } else { console.error('No data loaded!') } diff --git a/assets/js/index.js b/assets/js/index.js index 67fa00144..d10fbbbe7 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -1,5 +1,5 @@ import React from 'react' -import ReactDOM from 'react-dom' +import { createRoot } from 'react-dom/client' import App from './Components/App' import getInitialData from './getInitialData' import { theme } from '@instructure/canvas-theme' @@ -7,4 +7,7 @@ import { theme } from '@instructure/canvas-theme' theme.use() const data = getInitialData() -ReactDOM.render(, document.getElementById('root')) +// Updated from react-dom's `render` to `createRoot.render` for React 18: +// https://react.dev/blog/2022/03/08/react-18-upgrade-guide#updates-to-client-rendering-apis +const root = createRoot(document.getElementById('root')) +root.render() \ No newline at end of file diff --git a/build/nginx/Dockerfile.build b/build/nginx/Dockerfile.build index e85c60732..bee81c285 100644 --- a/build/nginx/Dockerfile.build +++ b/build/nginx/Dockerfile.build @@ -1,4 +1,4 @@ -FROM php:8.2-fpm +FROM php:8.4.2-fpm RUN apt-get update -y \ && apt-get install -y nginx libpng-dev zlib1g-dev git unzip diff --git a/build/nginx/Dockerfile.php.pdo.mysql b/build/nginx/Dockerfile.php.pdo.mysql index 020eb52d6..d46d6e0f3 100644 --- a/build/nginx/Dockerfile.php.pdo.mysql +++ b/build/nginx/Dockerfile.php.pdo.mysql @@ -1,4 +1,4 @@ -FROM php:8.2-fpm +FROM php:8.4.2-fpm # PHP extensions RUN apt-get update && apt-get install -y libpng-dev zlib1g-dev git unzip diff --git a/composer.json b/composer.json index 4964ff99e..0b094d759 100644 --- a/composer.json +++ b/composer.json @@ -7,13 +7,12 @@ "version": "3.1.0", "license": "GPL-3.0-only", "require": { - "php": "^7.4.0 || ^8.1 || ^8.2", + "php": "^7.4.0 || ^8.1 || ^8.2 || ^8.4", "ext-ctype": "*", "ext-iconv": "*", "ext-sodium": "*", - "ucfopen/phpally": "~1.2.1", + "aws/aws-sdk-php": "^3.324", "composer/package-versions-deprecated": "1.11.99.3", - "doctrine/annotations": "^1.0", "doctrine/doctrine-bundle": "^2.4", "doctrine/doctrine-migrations-bundle": "^3.1", "doctrine/orm": "^2.9", @@ -24,49 +23,52 @@ "mpdf/mpdf": "^8.0", "oro/doctrine-extensions": "^2.0", "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^0.5.3", "sensio/framework-extra-bundle": "^6.2", + "sunra/php-simple-html-dom-parser": "1.5.2", "symfony/apache-pack": "^1.0", - "symfony/asset": "6.0.*", - "symfony/console": "6.0.*", - "symfony/doctrine-messenger": "6.0.*", - "symfony/dotenv": "6.0.*", - "symfony/expression-language": "6.0.*", + "symfony/asset": "^6.4", + "symfony/console": "^6.4", + "symfony/doctrine-messenger": "^6.4", + "symfony/dotenv": "^6.4", + "symfony/expression-language": "^6.4", "symfony/flex": "^1.3.1", - "symfony/form": "6.0.*", - "symfony/framework-bundle": "6.0.*", - "symfony/http-client": "6.0.*", - "symfony/intl": "6.0.*", - "symfony/mailer": "6.0.*", - "symfony/messenger": "6.0.*", + "symfony/form": "^6.4", + "symfony/framework-bundle": "^6.4", + "symfony/http-client": "^6.4", + "symfony/intl": "^6.4", + "symfony/mailer": "^6.4", + "symfony/messenger": "^6.4", "symfony/monolog-bundle": "^3.1", - "symfony/notifier": "6.0.*", - "symfony/process": "6.0.*", - "symfony/property-access": "6.0.*", - "symfony/property-info": "6.0.*", - "symfony/proxy-manager-bridge": "6.0.*", - "symfony/security-bundle": "6.0.*", - "symfony/serializer": "6.0.*", - "symfony/string": "6.0.*", - "symfony/translation": "6.0.*", - "symfony/twig-bundle": "6.0.*", - "symfony/uid": "6.0.*", - "symfony/validator": "6.0.*", - "symfony/web-link": "6.0.*", + "symfony/notifier": "^6.4", + "symfony/process": "^6.4", + "symfony/property-access": "^6.4", + "symfony/property-info": "^6.4", + "symfony/proxy-manager-bridge": "^6.4", + "symfony/security-bundle": "^6.4", + "symfony/serializer": "^6.4", + "symfony/string": "^6.4", + "symfony/translation": "^6.4", + "symfony/twig-bundle": "^6.4", + "symfony/uid": "^6.4", + "symfony/validator": "^6.4", + "symfony/web-link": "^6.4", "symfony/webpack-encore-bundle": "^1.7", - "symfony/yaml": "6.0.*", + "symfony/yaml": "^6.4", "twig/extra-bundle": "^2.12|^3.0", - "twig/twig": "^2.12|^3.0" + "twig/twig": "^2.12|^3.0", + "ucfopen/phpally": "~1.2.1" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "^3.4", "phpunit/phpunit": "^9.5", - "symfony/browser-kit": "6.0.*", - "symfony/css-selector": "6.0.*", - "symfony/debug-bundle": "6.0.*", + "symfony/browser-kit": "^6.4", + "symfony/css-selector": "^6.4", + "symfony/debug-bundle": "^6.4", "symfony/maker-bundle": "^1.0", - "symfony/phpunit-bridge": "^6.0", - "symfony/stopwatch": "6.0.*", - "symfony/web-profiler-bundle": "6.0.*" + "symfony/phpunit-bridge": "^6.4", + "symfony/stopwatch": "^6.4", + "symfony/web-profiler-bundle": "^6.4" }, "config": { "preferred-install": { @@ -104,7 +106,7 @@ "extra": { "symfony": { "allow-contrib": false, - "require": "6.0.*" + "require": "^6.4" } }, "repositories": [ diff --git a/composer.lock b/composer.lock index d0c8251cb..4c865b58d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,160 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6d8dbbf76adee951d6466d92facf46d0", + "content-hash": "b3ccfa582029cdf621ca1e255bdbcde8", "packages": [ + { + "name": "aws/aws-crt-php", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" + }, + "time": "2024-10-18T22:15:13+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.336.11", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "442039c766a82f06ecfecb0ac2c610d6aaba228d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/442039c766a82f06ecfecb0ac2c610d6aaba228d", + "reference": "442039c766a82f06ecfecb0ac2c610d6aaba228d", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.2.3", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Aws\\": "src/" + }, + "exclude-from-classmap": [ + "src/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.336.11" + }, + "time": "2025-01-08T19:06:59+00:00" + }, { "name": "composer/package-versions-deprecated", "version": "1.11.99.3", @@ -81,31 +233,31 @@ }, { "name": "doctrine/annotations", - "version": "1.14.3", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af" + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", - "reference": "fb0d71a7393298a7b232cbf4c8b1f73f3ec3d5af", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/901c2ee5d26eb64ff43c47976e114bf00843acf7", + "reference": "901c2ee5d26eb64ff43c47976e114bf00843acf7", "shasum": "" }, "require": { - "doctrine/lexer": "^1 || ^2", + "doctrine/lexer": "^2 || ^3", "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", + "php": "^7.2 || ^8.0", "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "doctrine/cache": "^2.0", + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.10.28", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "vimeo/psalm": "^4.10" + "symfony/cache": "^5.4 || ^6.4 || ^7", + "vimeo/psalm": "^4.30 || ^5.14" }, "suggest": { "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" @@ -151,9 +303,9 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.14.3" + "source": "https://github.com/doctrine/annotations/tree/2.0.2" }, - "time": "2023-02-01T09:20:38+00:00" + "time": "2024-09-05T10:17:24+00:00" }, { "name": "doctrine/cache", @@ -336,20 +488,20 @@ }, { "name": "doctrine/common", - "version": "3.4.4", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a" + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a", - "reference": "0aad4b7ab7ce8c6602dfbb1e1a24581275fb9d1a", + "url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5", + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5", "shasum": "" }, "require": { - "doctrine/persistence": "^2.0 || ^3.0", + "doctrine/persistence": "^2.0 || ^3.0 || ^4.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -407,7 +559,7 @@ ], "support": { "issues": "https://github.com/doctrine/common/issues", - "source": "https://github.com/doctrine/common/tree/3.4.4" + "source": "https://github.com/doctrine/common/tree/3.5.0" }, "funding": [ { @@ -423,20 +575,20 @@ "type": "tidelift" } ], - "time": "2024-04-16T13:35:33+00:00" + "time": "2025-01-01T22:12:03+00:00" }, { "name": "doctrine/dbal", - "version": "3.8.4", + "version": "3.9.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd" + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/b05e48a745f722801f55408d0dbd8003b403dbbd", - "reference": "b05e48a745f722801f55408d0dbd8003b403dbbd", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", + "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", "shasum": "" }, "require": { @@ -452,12 +604,12 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.58", - "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.16", + "phpstan/phpstan": "1.12.6", + "phpstan/phpstan-strict-rules": "^1.6", + "phpunit/phpunit": "9.6.20", "psalm/plugin-phpunit": "0.18.4", "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.9.0", + "squizlabs/php_codesniffer": "3.10.2", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0", "vimeo/psalm": "4.30.0" @@ -520,7 +672,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.8.4" + "source": "https://github.com/doctrine/dbal/tree/3.9.3" }, "funding": [ { @@ -536,33 +688,31 @@ "type": "tidelift" } ], - "time": "2024-04-25T07:04:44+00:00" + "time": "2024-10-10T17:56:43+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.4", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", + "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", + "doctrine/coding-standard": "^9 || ^12", + "phpstan/phpstan": "1.4.10 || 2.0.3", + "phpstan/phpstan-phpunit": "^1.0 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -570,7 +720,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -581,22 +731,22 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.4" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2024-12-07T21:18:45+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "2.12.0", + "version": "2.13.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "5418e811a14724068e95e0ba43353b903ada530f" + "reference": "2740ad8b8739b39ab37d409c972b092f632b025a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/5418e811a14724068e95e0ba43353b903ada530f", - "reference": "5418e811a14724068e95e0ba43353b903ada530f", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/2740ad8b8739b39ab37d409c972b092f632b025a", + "reference": "2740ad8b8739b39ab37d409c972b092f632b025a", "shasum": "" }, "require": { @@ -610,7 +760,7 @@ "symfony/console": "^5.4 || ^6.0 || ^7.0", "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0", + "symfony/doctrine-bridge": "^5.4.46 || ^6.4.3 || ^7.0.3", "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" @@ -687,7 +837,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.12.0" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.13.1" }, "funding": [ { @@ -703,20 +853,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T07:20:37+00:00" + "time": "2024-11-08T23:27:54+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "3.3.0", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835" + "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1dd42906a5fb9c5960723e2ebb45c68006493835", - "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", + "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", "shasum": "" }, "require": { @@ -727,6 +877,7 @@ "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { + "composer/semver": "^3.0", "doctrine/coding-standard": "^12", "doctrine/orm": "^2.6 || ^3", "doctrine/persistence": "^2.0 || ^3 ", @@ -778,7 +929,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.0" + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.1" }, "funding": [ { @@ -794,20 +945,20 @@ "type": "tidelift" } ], - "time": "2023-11-13T19:44:41+00:00" + "time": "2024-05-14T20:32:18+00:00" }, { "name": "doctrine/event-manager", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", + "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", "shasum": "" }, "require": { @@ -817,10 +968,10 @@ "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^12", "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.28" + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" }, "type": "library", "autoload": { @@ -869,7 +1020,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.1" }, "funding": [ { @@ -885,7 +1036,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:59:15+00:00" + "time": "2024-05-22T20:47:39+00:00" }, { "name": "doctrine/inflector", @@ -1050,28 +1201,27 @@ }, { "name": "doctrine/lexer", - "version": "2.1.1", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", - "reference": "861c870e8b75f7c8f69c146c7f89cc1c0f1b49b6", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.21" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -1108,7 +1258,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.1" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -1124,25 +1274,25 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:35:39+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "doctrine/migrations", - "version": "3.7.4", + "version": "3.8.2", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "954e0a314c2f0eb9fb418210445111747de254a6" + "reference": "5007eb1168691225ac305fe16856755c20860842" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/954e0a314c2f0eb9fb418210445111747de254a6", - "reference": "954e0a314c2f0eb9fb418210445111747de254a6", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/5007eb1168691225ac305fe16856755c20860842", + "reference": "5007eb1168691225ac305fe16856755c20860842", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/dbal": "^3.5.1 || ^4", + "doctrine/dbal": "^3.6 || ^4", "doctrine/deprecations": "^0.5.3 || ^1", "doctrine/event-manager": "^1.2 || ^2.0", "php": "^8.1", @@ -1160,6 +1310,7 @@ "doctrine/persistence": "^2 || ^3", "doctrine/sql-formatter": "^1.0", "ext-pdo_sqlite": "*", + "fig/log-test": "^1", "phpstan/phpstan": "^1.10", "phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-phpunit": "^1.3", @@ -1180,7 +1331,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Migrations\\": "lib/Doctrine/Migrations" + "Doctrine\\Migrations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1210,7 +1361,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.7.4" + "source": "https://github.com/doctrine/migrations/tree/3.8.2" }, "funding": [ { @@ -1226,20 +1377,20 @@ "type": "tidelift" } ], - "time": "2024-03-06T13:41:11+00:00" + "time": "2024-10-10T21:35:27+00:00" }, { "name": "doctrine/orm", - "version": "2.19.5", + "version": "2.20.1", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "94986af28452da42a46a4489d1c958a2e5d710e5" + "reference": "e3cabade99ebccc6ba078884c1c5f250866a494e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/94986af28452da42a46a4489d1c958a2e5d710e5", - "reference": "94986af28452da42a46a4489d1c958a2e5d710e5", + "url": "https://api.github.com/repos/doctrine/orm/zipball/e3cabade99ebccc6ba078884c1c5f250866a494e", + "reference": "e3cabade99ebccc6ba078884c1c5f250866a494e", "shasum": "" }, "require": { @@ -1268,14 +1419,15 @@ "doctrine/annotations": "^1.13 || ^2", "doctrine/coding-standard": "^9.0.2 || ^12.0", "phpbench/phpbench": "^0.16.10 || ^1.0", - "phpstan/phpstan": "~1.4.10 || 1.10.59", + "phpstan/extension-installer": "~1.1.0 || ^1.4", + "phpstan/phpstan": "~1.4.10 || 2.0.3", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "4.30.0 || 5.22.2" + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1325,22 +1477,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.19.5" + "source": "https://github.com/doctrine/orm/tree/2.20.1" }, - "time": "2024-04-30T06:49:54+00:00" + "time": "2024-12-19T06:48:36+00:00" }, { "name": "doctrine/persistence", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "477da35bd0255e032826f440b94b3e37f2d56f42" + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/477da35bd0255e032826f440b94b3e37f2d56f42", - "reference": "477da35bd0255e032826f440b94b3e37f2d56f42", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/0ea965320cec355dba75031c1b23d4c78362e3ff", + "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff", "shasum": "" }, "require": { @@ -1352,15 +1504,13 @@ "doctrine/common": "<2.10" }, "require-dev": { - "composer/package-versions-deprecated": "^1.11", - "doctrine/coding-standard": "^11", + "doctrine/coding-standard": "^12", "doctrine/common": "^3.0", - "phpstan/phpstan": "1.9.4", + "phpstan/phpstan": "1.12.7", "phpstan/phpstan-phpunit": "^1", "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.3.0" + "phpunit/phpunit": "^8.5.38 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -1409,7 +1559,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.3.2" + "source": "https://github.com/doctrine/persistence/tree/3.4.0" }, "funding": [ { @@ -1425,27 +1575,31 @@ "type": "tidelift" } ], - "time": "2024-03-12T14:54:36+00:00" + "time": "2024-10-30T19:48:12+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.2.0", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc" + "reference": "b784cbde727cf806721451dde40eff4fec3bbe86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc", - "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/b784cbde727cf806721451dde40eff4fec3bbe86", + "reference": "b784cbde727cf806721451dde40eff4fec3bbe86", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4" + "doctrine/coding-standard": "^12", + "ergebnis/phpunit-slow-test-detector": "^2.14", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.24" }, "bin": [ "bin/sql-formatter" @@ -1475,22 +1629,22 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.1" }, - "time": "2023-08-16T21:49:04+00:00" + "time": "2024-10-21T18:21:57+00:00" }, { "name": "egulias/email-validator", - "version": "4.0.2", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + "reference": "b115554301161fa21467629f1e1391c1936de517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b115554301161fa21467629f1e1391c1936de517", + "reference": "b115554301161fa21467629f1e1391c1936de517", "shasum": "" }, "require": { @@ -1536,7 +1690,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.3" }, "funding": [ { @@ -1544,7 +1698,7 @@ "type": "github" } ], - "time": "2023-10-06T06:47:41+00:00" + "time": "2024-12-27T00:36:43+00:00" }, { "name": "firebase/php-jwt", @@ -1636,8 +1790,8 @@ "type": "library", "extra": { "thanks": { - "name": "ocramius/proxy-manager", - "url": "https://github.com/Ocramius/ProxyManager" + "url": "https://github.com/Ocramius/ProxyManager", + "name": "ocramius/proxy-manager" } }, "autoload": { @@ -1687,22 +1841,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.8.1", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", - "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1713,9 +1867,9 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "guzzle/client-integration-tests": "3.0.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1793,7 +1947,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -1809,20 +1963,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:35:24+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.2", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", - "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { @@ -1830,7 +1984,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { @@ -1876,7 +2030,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.2" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -1892,20 +2046,20 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:19:20+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.6.2", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", - "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { @@ -1920,8 +2074,8 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.36 || ^9.6.15" + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1992,7 +2146,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.2" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -2008,24 +2162,24 @@ "type": "tidelift" } ], - "time": "2023-12-03T20:05:35+00:00" + "time": "2024-07-18T11:15:46+00:00" }, { "name": "htmlawed/htmlawed", - "version": "1.2.6", + "version": "1.2.15.1", "source": { "type": "git", "url": "https://github.com/kesar/HTMLawed.git", - "reference": "c733124f21c0330be18d7b0f7f0944a19be6791f" + "reference": "76cfddd6877f4afd395cb0a70ca246d525d2837a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kesar/HTMLawed/zipball/c733124f21c0330be18d7b0f7f0944a19be6791f", - "reference": "c733124f21c0330be18d7b0f7f0944a19be6791f", + "url": "https://api.github.com/repos/kesar/HTMLawed/zipball/76cfddd6877f4afd395cb0a70ca246d525d2837a", + "reference": "76cfddd6877f4afd395cb0a70ca246d525d2837a", "shasum": "" }, "require": { - "php": ">4.4.0" + "php": ">=4.4" }, "type": "library", "autoload": { @@ -2035,30 +2189,42 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "GPL-2.0+", - "LGPL-3.0" + "GPL-2.0-or-later", + "LGPL-3.0-only" ], "authors": [ { "name": "Santosh Patnaik", - "homepage": "http://www.bioinformatics.org/people/index.php?user_hash=558b661f92d0ff7b", - "role": "Developer" + "email": "drpatnaikREMOVECAPS@yahoo.com", + "role": "Creator and developer" } ], - "description": "htmLawed - Process text with HTML markup to make it more compliant with HTML standards and administrative policies", - "homepage": "http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/", + "description": "Official htmLawed PHP library for HTML filtering", + "homepage": "https://bioinformatics.org/phplabware/internal_utilities/htmLawed", "keywords": [ - "HTMLtidy", + "clean", + "compliance", + "filter", + "filtering", + "htm", "html", + "input", + "purify", + "safe", + "safety", "sanitize", - "strip", - "tags" + "sanitizer", + "standards", + "text", + "xss" ], "support": { + "docs": "https://bioinformatics.org/phplabware/internal_utilities/htmLawed", + "forum": "https://bioinformatics.org/phplabware/internal_utilities/htmLawed", "issues": "https://github.com/kesar/HTMLawed/issues", - "source": "https://github.com/kesar/HTMLawed/tree/1.2.6" + "source": "https://bioinformatics.org/phplabware/internal_utilities/htmLawed" }, - "time": "2022-02-14T20:32:51+00:00" + "time": "2024-06-24T16:20:15+00:00" }, { "name": "kaltura/api-client-library", @@ -2110,16 +2276,16 @@ }, { "name": "knplabs/knp-snappy", - "version": "v1.5.0", + "version": "v1.5.1", "source": { "type": "git", "url": "https://github.com/KnpLabs/snappy.git", - "reference": "98468898b50c09f26d56d905b79b0f52a2215da6" + "reference": "3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/98468898b50c09f26d56d905b79b0f52a2215da6", - "reference": "98468898b50c09f26d56d905b79b0f52a2215da6", + "url": "https://api.github.com/repos/KnpLabs/snappy/zipball/3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7", + "reference": "3dd138e9e47de91cd2e056c5e6e1a0dd72547ee7", "shasum": "" }, "require": { @@ -2171,22 +2337,22 @@ ], "support": { "issues": "https://github.com/KnpLabs/snappy/issues", - "source": "https://github.com/KnpLabs/snappy/tree/v1.5.0" + "source": "https://github.com/KnpLabs/snappy/tree/v1.5.1" }, - "time": "2023-12-18T09:12:11+00:00" + "time": "2025-01-06T16:53:26+00:00" }, { "name": "knplabs/knp-snappy-bundle", - "version": "v1.10.1", + "version": "v1.10.4", "source": { "type": "git", "url": "https://github.com/KnpLabs/KnpSnappyBundle.git", - "reference": "24c61f0b52e8fff60b42b9fac5f2e776e22177e3" + "reference": "df217e5deed3397de88b7eb96de1d7c0cd7ed9e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/KnpLabs/KnpSnappyBundle/zipball/24c61f0b52e8fff60b42b9fac5f2e776e22177e3", - "reference": "24c61f0b52e8fff60b42b9fac5f2e776e22177e3", + "url": "https://api.github.com/repos/KnpLabs/KnpSnappyBundle/zipball/df217e5deed3397de88b7eb96de1d7c0cd7ed9e9", + "reference": "df217e5deed3397de88b7eb96de1d7c0cd7ed9e9", "shasum": "" }, "require": { @@ -2229,38 +2395,37 @@ ], "support": { "issues": "https://github.com/KnpLabs/KnpSnappyBundle/issues", - "source": "https://github.com/KnpLabs/KnpSnappyBundle/tree/v1.10.1" + "source": "https://github.com/KnpLabs/KnpSnappyBundle/tree/v1.10.4" }, - "time": "2024-04-19T09:05:01+00:00" + "time": "2025-01-14T07:31:54+00:00" }, { "name": "knpuniversity/oauth2-client-bundle", - "version": "v2.18.1", + "version": "v2.18.3", "source": { "type": "git", "url": "https://github.com/knpuniversity/oauth2-client-bundle.git", - "reference": "1d59f49f164805b45f95f92cf743781bc2ba7d2b" + "reference": "c38ca88a70aae3694ca346a41b13b9a8f6e33ed4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/knpuniversity/oauth2-client-bundle/zipball/1d59f49f164805b45f95f92cf743781bc2ba7d2b", - "reference": "1d59f49f164805b45f95f92cf743781bc2ba7d2b", + "url": "https://api.github.com/repos/knpuniversity/oauth2-client-bundle/zipball/c38ca88a70aae3694ca346a41b13b9a8f6e33ed4", + "reference": "c38ca88a70aae3694ca346a41b13b9a8f6e33ed4", "shasum": "" }, "require": { "league/oauth2-client": "^2.0", "php": ">=8.1", - "symfony/dependency-injection": "^4.4|^5.0|^6.0|^7.0", - "symfony/framework-bundle": "^4.4|^5.0|^6.0|^7.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0|^7.0", - "symfony/routing": "^4.4|^5.0|^6.0|^7.0" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0" }, "require-dev": { "league/oauth2-facebook": "^1.1|^2.0", - "phpstan/phpstan": "^1.0", - "symfony/phpunit-bridge": "^5.3.1|^6.0|^7.0", - "symfony/security-guard": "^4.4|^5.0|^6.0|^7.0", - "symfony/yaml": "^4.4|^5.0|^6.0|^7.0" + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0", + "symfony/security-guard": "^5.4", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "suggest": { "symfony/security-guard": "For integration with Symfony's Guard Security layer" @@ -2289,34 +2454,34 @@ ], "support": { "issues": "https://github.com/knpuniversity/oauth2-client-bundle/issues", - "source": "https://github.com/knpuniversity/oauth2-client-bundle/tree/v2.18.1" + "source": "https://github.com/knpuniversity/oauth2-client-bundle/tree/v2.18.3" }, - "time": "2024-02-14T17:41:28+00:00" + "time": "2024-10-02T14:26:09+00:00" }, { "name": "laminas/laminas-code", - "version": "4.13.0", + "version": "4.16.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "7353d4099ad5388e84737dd16994316a04f48dbf" + "reference": "1793e78dad4108b594084d05d1fb818b85b110af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/7353d4099ad5388e84737dd16994316a04f48dbf", - "reference": "7353d4099ad5388e84737dd16994316a04f48dbf", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", + "reference": "1793e78dad4108b594084d05d1fb818b85b110af", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "doctrine/annotations": "^2.0.1", "ext-phar": "*", - "laminas/laminas-coding-standard": "^2.5.0", - "laminas/laminas-stdlib": "^3.17.0", - "phpunit/phpunit": "^10.3.3", - "psalm/plugin-phpunit": "^0.18.4", + "laminas/laminas-coding-standard": "^3.0.0", + "laminas/laminas-stdlib": "^3.18.0", + "phpunit/phpunit": "^10.5.37", + "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.15.0" }, "suggest": { @@ -2354,39 +2519,34 @@ "type": "community_bridge" } ], - "time": "2023-10-18T10:00:55+00:00" + "time": "2024-11-20T13:15:13+00:00" }, { "name": "league/oauth2-client", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-client.git", - "reference": "160d6274b03562ebeb55ed18399281d8118b76c8" + "reference": "3d5cf8d0543731dfb725ab30e4d7289891991e13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/160d6274b03562ebeb55ed18399281d8118b76c8", - "reference": "160d6274b03562ebeb55ed18399281d8118b76c8", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/3d5cf8d0543731dfb725ab30e4d7289891991e13", + "reference": "3d5cf8d0543731dfb725ab30e4d7289891991e13", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "^6.0 || ^7.0", - "paragonie/random_compat": "^1 || ^2 || ^9.99", - "php": "^5.6 || ^7.0 || ^8.0" + "ext-json": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "php": "^7.1 || >=8.0.0 <8.5.0" }, "require-dev": { "mockery/mockery": "^1.3.5", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", - "squizlabs/php_codesniffer": "^2.3 || ^3.0" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.11" }, "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "League\\OAuth2\\Client\\": "src/" @@ -2422,22 +2582,22 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-client/issues", - "source": "https://github.com/thephpleague/oauth2-client/tree/2.7.0" + "source": "https://github.com/thephpleague/oauth2-client/tree/2.8.0" }, - "time": "2023-04-16T18:19:15+00:00" + "time": "2024-12-11T05:05:52+00:00" }, { "name": "monolog/monolog", - "version": "3.6.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", - "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4", + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4", "shasum": "" }, "require": { @@ -2457,12 +2617,14 @@ "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.5.17", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -2513,7 +2675,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.6.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.1" }, "funding": [ { @@ -2525,20 +2687,20 @@ "type": "tidelift" } ], - "time": "2024-04-12T21:02:21+00:00" + "time": "2024-12-05T17:15:07+00:00" }, { "name": "mpdf/mpdf", - "version": "v8.2.3", + "version": "v8.2.5", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "6f723a96becf989a831e38caf758d28364a69939" + "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/6f723a96becf989a831e38caf758d28364a69939", - "reference": "6f723a96becf989a831e38caf758d28364a69939", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/e175b05e3e00977b85feb96a8cccb174ac63621f", + "reference": "e175b05e3e00977b85feb96a8cccb174ac63621f", "shasum": "" }, "require": { @@ -2548,7 +2710,7 @@ "mpdf/psr-log-aware-trait": "^2.0 || ^3.0", "myclabs/deep-copy": "^1.7", "paragonie/random_compat": "^1.4|^2.0|^9.99.99", - "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", "psr/http-message": "^1.0 || ^2.0", "psr/log": "^1.0 || ^2.0 || ^3.0", "setasign/fpdi": "^2.1" @@ -2596,7 +2758,7 @@ "utf-8" ], "support": { - "docs": "http://mpdf.github.io", + "docs": "https://mpdf.github.io", "issues": "https://github.com/mpdf/mpdf/issues", "source": "https://github.com/mpdf/mpdf" }, @@ -2606,7 +2768,7 @@ "type": "custom" } ], - "time": "2024-03-11T12:55:53+00:00" + "time": "2024-11-18T15:30:42+00:00" }, { "name": "mpdf/psr-http-message-shim", @@ -2700,18 +2862,84 @@ }, "time": "2023-05-03T06:19:36+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + }, + "time": "2024-09-04T18:46:31+00:00" + }, { "name": "myclabs/deep-copy", - "version": "1.11.1", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -2719,11 +2947,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -2749,7 +2978,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -2757,30 +2986,34 @@ "type": "tidelift" } ], - "time": "2023-03-08T13:26:56+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "oro/doctrine-extensions", - "version": "2.0.2", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/oroinc/doctrine-extensions.git", - "reference": "478101fdb37e7a3bd4efad78b6e36fc49c26055f" + "reference": "98dea7afc2637a6f1434b94a90d3d807155fe34e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/oroinc/doctrine-extensions/zipball/478101fdb37e7a3bd4efad78b6e36fc49c26055f", - "reference": "478101fdb37e7a3bd4efad78b6e36fc49c26055f", + "url": "https://api.github.com/repos/oroinc/doctrine-extensions/zipball/98dea7afc2637a6f1434b94a90d3d807155fe34e", + "reference": "98dea7afc2637a6f1434b94a90d3d807155fe34e", "shasum": "" }, "require": { - "doctrine/orm": ">=2.6", - "php": ">=7.3" + "doctrine/dbal": "^2.6|^3", + "doctrine/lexer": "^2|^3", + "doctrine/orm": "^2.6", + "php": ">=8.0" }, "require-dev": { + "doctrine/annotations": "^1.0|^2.0", "doctrine/data-fixtures": "^1.3", "phpunit/phpunit": "9.*", "squizlabs/php_codesniffer": "3.5.*", + "symfony/cache": "5.*", "symfony/yaml": "5.*" }, "type": "library", @@ -2813,9 +3046,9 @@ ], "support": { "issues": "https://github.com/oroinc/doctrine-extensions/issues", - "source": "https://github.com/oroinc/doctrine-extensions/tree/2.0.2" + "source": "https://github.com/oroinc/doctrine-extensions/tree/2.0.5" }, - "time": "2022-05-10T14:09:20+00:00" + "time": "2024-11-20T13:22:34+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -2872,35 +3105,28 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.0", + "version": "5.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "298d2febfe79d03fe714eb871d5538da55205b1a" + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/298d2febfe79d03fe714eb871d5538da55205b1a", - "reference": "298d2febfe79d03fe714eb871d5538da55205b1a", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.4 || ^8.0", + "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpdocumentor/type-resolver": "^1.3", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" }, "type": "library", "extra": { @@ -2924,39 +3150,36 @@ }, { "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" }, - "time": "2024-04-09T21:13:58+00:00" + "time": "2021-10-19T17:43:47+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d", + "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.1", @@ -2988,39 +3211,41 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2022-10-14T12:47:21+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.28.0", + "version": "0.5.7", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb" + "reference": "816e826ce0b7fb32098d8cb6de62511ce6021cea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", - "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/816e826ce0b7fb32098d8cb6de62511ce6021cea", + "reference": "816e826ce0b7fb32098d8cb6de62511ce6021cea", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan": "^0.12.87", + "phpstan/phpstan-strict-rules": "^0.12.5", "phpunit/phpunit": "^9.5", "symfony/process": "^5.2" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.5-dev" + } + }, "autoload": { "psr-4": { "PHPStan\\PhpDocParser\\": [ @@ -3035,9 +3260,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.28.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/0.5.7" }, - "time": "2024-04-03T18:51:33+00:00" + "time": "2021-09-12T11:52:00+00:00" }, { "name": "psr/cache", @@ -3088,6 +3313,54 @@ }, "time": "2021-02-03T23:26:27+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, { "name": "psr/container", "version": "2.0.2", @@ -3245,20 +3518,20 @@ }, { "name": "psr/http-factory", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "e616d01114759c4c489f93b099585439f795fe35" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", - "reference": "e616d01114759c4c489f93b099585439f795fe35", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", + "php": ">=7.1", "psr/http-message": "^1.0 || ^2.0" }, "type": "library", @@ -3282,7 +3555,7 @@ "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -3294,9 +3567,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/1.0.2" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-04-10T20:10:41+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", @@ -3409,16 +3682,16 @@ }, { "name": "psr/log", - "version": "3.0.0", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { @@ -3453,9 +3726,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "ralouphie/getallheaders", @@ -3581,16 +3854,16 @@ }, { "name": "setasign/fpdi", - "version": "v2.6.0", + "version": "v2.6.2", "source": { "type": "git", "url": "https://github.com/Setasign/FPDI.git", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad" + "reference": "9e013b376939c0d4029f54150d2a16f3c67a5797" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/a6db878129ec6c7e141316ee71872923e7f1b7ad", - "reference": "a6db878129ec6c7e141316ee71872923e7f1b7ad", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/9e013b376939c0d4029f54150d2a16f3c67a5797", + "reference": "9e013b376939c0d4029f54150d2a16f3c67a5797", "shasum": "" }, "require": { @@ -3641,7 +3914,7 @@ ], "support": { "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.6.0" + "source": "https://github.com/Setasign/FPDI/tree/v2.6.2" }, "funding": [ { @@ -3649,61 +3922,110 @@ "type": "tidelift" } ], - "time": "2023-12-11T16:03:32+00:00" + "time": "2024-12-10T13:12:19+00:00" }, { - "name": "symfony/apache-pack", - "version": "v1.0.1", + "name": "sunra/php-simple-html-dom-parser", + "version": "v1.5.2", "source": { "type": "git", - "url": "https://github.com/symfony/apache-pack.git", - "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c" + "url": "https://github.com/sunra/php-simple-html-dom-parser.git", + "reference": "75b9b1cb64502d8f8c04dc11b5906b969af247c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/apache-pack/zipball/3aa5818d73ad2551281fc58a75afd9ca82622e6c", - "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "url": "https://api.github.com/repos/sunra/php-simple-html-dom-parser/zipball/75b9b1cb64502d8f8c04dc11b5906b969af247c6", + "reference": "75b9b1cb64502d8f8c04dc11b5906b969af247c6", "shasum": "" }, - "type": "symfony-pack", + "require": { + "ext-mbstring": "*", + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "Sunra\\PhpSimple\\HtmlDomParser": "Src/" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "A pack for Apache support in Symfony", - "support": { - "issues": "https://github.com/symfony/apache-pack/issues", - "source": "https://github.com/symfony/apache-pack/tree/master" - }, + "authors": [ + { + "name": "Sunra", + "email": "sunra@yandex.ru", + "homepage": "https://github.com/sunra" + }, + { + "name": "S.C. Chen", + "homepage": "http://sourceforge.net/projects/simplehtmldom/" + } + ], + "description": "Composer adaptation of: A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way! Require PHP 5+. Supports invalid HTML. Find tags on an HTML page with selectors just like jQuery. Extract contents from HTML in a single line.", + "homepage": "https://github.com/sunra/php-simple-html-dom-parser", + "keywords": [ + "dom", + "html", + "parser" + ], + "support": { + "issues": "https://github.com/sunra/php-simple-html-dom-parser/issues", + "source": "https://github.com/sunra/php-simple-html-dom-parser/tree/master" + }, + "time": "2016-11-22T22:57:47+00:00" + }, + { + "name": "symfony/apache-pack", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/apache-pack.git", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/apache-pack/zipball/3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "reference": "3aa5818d73ad2551281fc58a75afd9ca82622e6c", + "shasum": "" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for Apache support in Symfony", + "support": { + "issues": "https://github.com/symfony/apache-pack/issues", + "source": "https://github.com/symfony/apache-pack/tree/master" + }, "time": "2017-12-12T01:46:35+00:00" }, { "name": "symfony/asset", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "d42c434e1a73d81cae7c75cd122f20fc80ac1a2b" + "reference": "2466c17d61d14539cddf77e57ebb9cc971185302" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/d42c434e1a73d81cae7c75cd122f20fc80ac1a2b", - "reference": "d42c434e1a73d81cae7c75cd122f20fc80ac1a2b", + "url": "https://api.github.com/repos/symfony/asset/zipball/2466c17d61d14539cddf77e57ebb9cc971185302", + "reference": "2466c17d61d14539cddf77e57ebb9cc971185302", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "symfony/http-foundation": "<5.4" }, "require-dev": { - "symfony/http-client": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0" - }, - "suggest": { - "symfony/http-foundation": "" + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3731,7 +4053,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v6.0.19" + "source": "https://github.com/symfony/asset/tree/v6.4.13" }, "funding": [ { @@ -3747,35 +4069,36 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/cache", - "version": "v6.4.7", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "b9e9b93c9817ec6c789c7943f5e54b57a041c16a" + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/b9e9b93c9817ec6c789c7943f5e54b57a041c16a", - "reference": "b9e9b93c9817ec6c789c7943f5e54b57a041c16a", + "url": "https://api.github.com/repos/symfony/cache/zipball/e7e983596b744c4539f31e79b0350a6cf5878a20", + "reference": "e7e983596b744c4539f31e79b0350a6cf5878a20", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^2.5|^3", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.3.6|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "conflict": { - "doctrine/dbal": "<2.13.1", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/var-dumper": "<5.4" + "doctrine/dbal": "<3.6", + "symfony/dependency-injection": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/var-dumper": "<6.4" }, "provide": { "psr/cache-implementation": "2.0|3.0", @@ -3784,15 +4107,16 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/filesystem": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/filesystem": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3827,7 +4151,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.7" + "source": "https://github.com/symfony/cache/tree/v7.2.1" }, "funding": [ { @@ -3843,20 +4167,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-12-07T08:08:50+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.4.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "2c9db6509a1b21dad229606897639d3284f54b2a" + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/2c9db6509a1b21dad229606897639d3284f54b2a", - "reference": "2c9db6509a1b21dad229606897639d3284f54b2a", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", + "reference": "15a4f8e5cd3bce9aeafc882b1acab39ec8de2c1b", "shasum": "" }, "require": { @@ -3865,12 +4189,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -3903,7 +4227,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/cache-contracts/tree/v3.5.1" }, "funding": [ { @@ -3919,20 +4243,94 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/config", - "version": "v6.4.7", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "51da0e4494d81bd7b5b5bd80319c55d8e0d7f4ff" + "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/51da0e4494d81bd7b5b5bd80319c55d8e0d7f4ff", - "reference": "51da0e4494d81bd7b5b5bd80319c55d8e0d7f4ff", + "url": "https://api.github.com/repos/symfony/config/zipball/4e55e7e4ffddd343671ea972216d4509f46c22ef", + "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef", "shasum": "" }, "require": { @@ -3978,7 +4376,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.7" + "source": "https://github.com/symfony/config/tree/v6.4.14" }, "funding": [ { @@ -3994,27 +4392,28 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-04T11:33:53+00:00" }, { "name": "symfony/console", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + "reference": "799445db3f15768ecc382ac5699e6da0520a0a04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "url": "https://api.github.com/repos/symfony/console/zipball/799445db3f15768ecc382ac5699e6da0520a0a04", + "reference": "799445db3f15768ecc382ac5699e6da0520a0a04", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -4028,18 +4427,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4068,12 +4465,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.19" + "source": "https://github.com/symfony/console/tree/v6.4.17" }, "funding": [ { @@ -4089,33 +4486,34 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-12-07T12:07:30+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.1.12", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "360c9d0948e1fe675336346d5862e8e55b378d90" + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/360c9d0948e1fe675336346d5862e8e55b378d90", - "reference": "360c9d0948e1fe675336346d5862e8e55b378d90", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/7a379d8871f6a36f01559c14e11141cc02eb8dc8", + "reference": "7a379d8871f6a36f01559c14e11141cc02eb8dc8", "shasum": "" }, "require": { "php": ">=8.1", "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/service-contracts": "^1.1.6|^2.0|^3.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.2.10|^7.0" }, "conflict": { "ext-psr": "<1.1|>=2", "symfony/config": "<6.1", "symfony/finder": "<5.4", - "symfony/proxy-manager-bridge": "<5.4", + "symfony/proxy-manager-bridge": "<6.3", "symfony/yaml": "<5.4" }, "provide": { @@ -4123,16 +4521,9 @@ "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^6.1", - "symfony/expression-language": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "symfony/config": "^6.1|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4160,7 +4551,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.1.12" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.16" }, "funding": [ { @@ -4176,20 +4567,20 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:43:30+00:00" + "time": "2024-11-25T14:52:46+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -4197,12 +4588,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -4227,7 +4618,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -4243,78 +4634,72 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v6.1.11", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "f50159673ec3f4a68b81db4712f4a5bbe47a9442" + "reference": "f12195479a55b77bc8427b48443b966622f4a18b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/f50159673ec3f4a68b81db4712f4a5bbe47a9442", - "reference": "f50159673ec3f4a68b81db4712f4a5bbe47a9442", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/f12195479a55b77bc8427b48443b966622f4a18b", + "reference": "f12195479a55b77bc8427b48443b966622f4a18b", "shasum": "" }, "require": { - "doctrine/event-manager": "^1|^2", - "doctrine/persistence": "^2|^3", - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "doctrine/event-manager": "^2", + "doctrine/persistence": "^3.1", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "doctrine/dbal": "<2.13.1", + "doctrine/collections": "<1.8", + "doctrine/dbal": "<3.6", "doctrine/lexer": "<1.1", - "doctrine/orm": "<2.7.4", - "phpunit/phpunit": "<5.4.3", - "symfony/cache": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/form": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/messenger": "<5.4", - "symfony/property-info": "<5.4", - "symfony/security-bundle": "<5.4", - "symfony/security-core": "<6.0", - "symfony/validator": "<5.4" + "doctrine/orm": "<2.15", + "symfony/cache": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/form": "<6.4.6|>=7,<7.0.6", + "symfony/http-foundation": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/lock": "<6.4", + "symfony/messenger": "<6.4", + "symfony/property-info": "<6.4", + "symfony/security-bundle": "<6.4", + "symfony/security-core": "<6.4", + "symfony/validator": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "doctrine/collections": "^1.0|^2.0", - "doctrine/data-fixtures": "^1.1", - "doctrine/dbal": "^2.13.1|^3.0", - "doctrine/orm": "^2.7.4", + "doctrine/collections": "^1.8|^2.0", + "doctrine/data-fixtures": "^1.1|^2", + "doctrine/dbal": "^3.6|^4", + "doctrine/orm": "^2.15|^3", "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/doctrine-messenger": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4.9|^6.0.9", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/proxy-manager-bridge": "^5.4|^6.0", - "symfony/security-core": "^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "doctrine/data-fixtures": "", - "doctrine/dbal": "", - "doctrine/orm": "", - "symfony/form": "", - "symfony/property-info": "", - "symfony/validator": "" + "symfony/cache": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/doctrine-messenger": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/form": "^6.4.6|^7.0.6", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/type-info": "^7.1", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "symfony-bridge", "autoload": { @@ -4342,7 +4727,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.1.11" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.2.2" }, "funding": [ { @@ -4358,35 +4743,35 @@ "type": "tidelift" } ], - "time": "2023-01-10T18:53:01+00:00" + "time": "2024-12-19T14:25:03+00:00" }, { "name": "symfony/doctrine-messenger", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-messenger.git", - "reference": "bf235c311bac1e882fe8943198e141302de2d4f9" + "reference": "c4afe708134a4506316955d1c009bc6091b16b2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/bf235c311bac1e882fe8943198e141302de2d4f9", - "reference": "bf235c311bac1e882fe8943198e141302de2d4f9", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/c4afe708134a4506316955d1c009bc6091b16b2d", + "reference": "c4afe708134a4506316955d1c009bc6091b16b2d", "shasum": "" }, "require": { - "doctrine/dbal": "^2.13|^3.0", - "php": ">=8.0.2", - "symfony/messenger": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" + "doctrine/dbal": "^2.13|^3|^4", + "php": ">=8.1", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { "doctrine/persistence": "<1.3" }, "require-dev": { "doctrine/persistence": "^1.3|^2|^3", - "symfony/property-access": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" }, "type": "symfony-messenger-bridge", "autoload": { @@ -4414,7 +4799,7 @@ "description": "Symfony Doctrine Messenger Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-messenger/tree/v6.0.19" + "source": "https://github.com/symfony/doctrine-messenger/tree/v6.4.13" }, "funding": [ { @@ -4430,28 +4815,32 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-10-18T09:45:38+00:00" }, { "name": "symfony/dotenv", - "version": "v6.0.19", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "9cee123707e689f7e06c09624c145d206468bcf2" + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/9cee123707e689f7e06c09624c145d206468bcf2", - "reference": "9cee123707e689f7e06c09624c145d206468bcf2", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac5e7e7e862d4d574258daf08bd569ba926e4a5", + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "conflict": { + "symfony/console": "<5.4", + "symfony/process": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4484,7 +4873,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.0.19" + "source": "https://github.com/symfony/dotenv/tree/v6.4.16" }, "funding": [ { @@ -4500,34 +4889,35 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-11-27T11:08:19+00:00" }, { "name": "symfony/error-handler", - "version": "v6.3.12", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "93a8400a7eaaaf385b2d6f71e30e064baa639629" + "reference": "6150b89186573046167796fa5f3f76601d5145f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/93a8400a7eaaaf385b2d6f71e30e064baa639629", - "reference": "93a8400a7eaaaf385b2d6f71e30e064baa639629", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/6150b89186573046167796fa5f3f76601d5145f8", + "reference": "6150b89186573046167796fa5f3f76601d5145f8", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^6.4|^7.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5" + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4558,7 +4948,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.3.12" + "source": "https://github.com/symfony/error-handler/tree/v7.2.1" }, "funding": [ { @@ -4574,28 +4964,28 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:35:58+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d84384f3f67de3cb650db64d685d70395dacfc3f", - "reference": "d84384f3f67de3cb650db64d685d70395dacfc3f", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -4604,13 +4994,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4638,7 +5028,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.7" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -4654,20 +5044,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "4e64b49bf370ade88e567de29465762e316e4224" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224", - "reference": "4e64b49bf370ade88e567de29465762e316e4224", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -4676,12 +5066,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -4714,7 +5104,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -4730,26 +5120,27 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/expression-language", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "d912aa436eeed66ae369a2b8a247249bed8f9a03" + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/d912aa436eeed66ae369a2b8a247249bed8f9a03", - "reference": "d912aa436eeed66ae369a2b8a247249bed8f9a03", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/3524904fb026356a5230cd197f9a4e6a61e0e7df", + "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/cache": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -4777,7 +5168,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v6.0.19" + "source": "https://github.com/symfony/expression-language/tree/v6.4.13" }, "funding": [ { @@ -4793,27 +5184,30 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-10-09T08:40:40+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3" + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/9919b5509ada52cc7f66f9a35c86a4a29955c9d3", - "reference": "9919b5509ada52cc7f66f9a35c86a4a29955c9d3", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -4840,7 +5234,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.6" + "source": "https://github.com/symfony/filesystem/tree/v7.2.0" }, "funding": [ { @@ -4856,27 +5250,27 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:36:20+00:00" + "time": "2024-10-25T15:15:23+00:00" }, { "name": "symfony/finder", - "version": "v6.4.7", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "511c48990be17358c23bf45c5d71ab85d40fb764" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/511c48990be17358c23bf45c5d71ab85d40fb764", - "reference": "511c48990be17358c23bf45c5d71ab85d40fb764", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -4904,7 +5298,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.7" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -4920,26 +5314,29 @@ "type": "tidelift" } ], - "time": "2024-04-23T10:36:43+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/flex", - "version": "v1.21.6", + "version": "v1.21.8", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "06b58a5e5b4c6528fb12e0fac5fea0db3f1e7ae8" + "reference": "bda5f869ac51c8e985a6fe9f964c4cb78228a369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/06b58a5e5b4c6528fb12e0fac5fea0db3f1e7ae8", - "reference": "06b58a5e5b4c6528fb12e0fac5fea0db3f1e7ae8", + "url": "https://api.github.com/repos/symfony/flex/zipball/bda5f869ac51c8e985a6fe9f964c4cb78228a369", + "reference": "bda5f869ac51c8e985a6fe9f964c4cb78228a369", "shasum": "" }, "require": { "composer-plugin-api": "^1.0|^2.0", "php": ">=7.1" }, + "conflict": { + "composer/semver": "<1.7.2" + }, "require-dev": { "composer/composer": "^1.0.2|^2.0", "symfony/dotenv": "^4.4|^5.0|^6.0", @@ -4969,7 +5366,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v1.21.6" + "source": "https://github.com/symfony/flex/tree/v1.21.8" }, "funding": [ { @@ -4985,65 +5382,60 @@ "type": "tidelift" } ], - "time": "2024-03-02T08:16:37+00:00" + "time": "2024-10-07T08:51:39+00:00" }, { "name": "symfony/form", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "bec07ecf4aac245183b8e0fa93eb68630415346e" + "reference": "0fe17f90af23908ddc11dc23507db98e66572046" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/bec07ecf4aac245183b8e0fa93eb68630415346e", - "reference": "bec07ecf4aac245183b8e0fa93eb68630415346e", + "url": "https://api.github.com/repos/symfony/form/zipball/0fe17f90af23908ddc11dc23507db98e66572046", + "reference": "0fe17f90af23908ddc11dc23507db98e66572046", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/options-resolver": "^5.4|^6.0", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/options-resolver": "^5.4|^6.0|^7.0", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-icu": "^1.21", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.23", - "symfony/property-access": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "phpunit/phpunit": "<5.4.3", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", - "symfony/doctrine-bridge": "<5.4", + "symfony/doctrine-bridge": "<5.4.21|>=6,<6.2.7", "symfony/error-handler": "<5.4", "symfony/framework-bundle": "<5.4", "symfony/http-kernel": "<5.4", - "symfony/translation": "<5.4", - "symfony/translation-contracts": "<1.1.7", - "symfony/twig-bridge": "<5.4" + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.3" }, "require-dev": { "doctrine/collections": "^1.0|^2.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "symfony/security-csrf": "For protecting forms against CSRF attacks.", - "symfony/twig-bridge": "For templating with Twig.", - "symfony/validator": "For form validation." + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/html-sanitizer": "^6.1|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/security-core": "^6.2|^7.0", + "symfony/security-csrf": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5071,7 +5463,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v6.0.19" + "source": "https://github.com/symfony/form/tree/v6.4.13" }, "funding": [ { @@ -5087,111 +5479,112 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-10-09T08:40:40+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "ee403597484be1073222373fc2962b44c36f5dd4" + "reference": "17d8ae2e7aa77154f942e8ac48849ac718b0963f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ee403597484be1073222373fc2962b44c36f5dd4", - "reference": "ee403597484be1073222373fc2962b44c36f5dd4", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/17d8ae2e7aa77154f942e8ac48849ac718b0963f", + "reference": "17d8ae2e7aa77154f942e8ac48849ac718b0963f", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.0.2", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4.5|^6.0.5", - "symfony/error-handler": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", + "php": ">=8.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/dependency-injection": "^6.4.12|^7.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.1|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.22", - "symfony/routing": "^5.4|^6.0" + "symfony/routing": "^6.4|^7.0" }, "conflict": { "doctrine/annotations": "<1.13.1", "doctrine/persistence": "<1.3", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "phpunit/phpunit": "<5.4.3", "symfony/asset": "<5.4", - "symfony/console": "<5.4", - "symfony/dom-crawler": "<5.4", + "symfony/asset-mapper": "<6.4", + "symfony/clock": "<6.3", + "symfony/console": "<5.4|>=7.0", + "symfony/dom-crawler": "<6.4", "symfony/dotenv": "<5.4", "symfony/form": "<5.4", - "symfony/http-client": "<5.4", + "symfony/http-client": "<6.3", "symfony/lock": "<5.4", "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/mime": "<5.4", + "symfony/messenger": "<6.3", + "symfony/mime": "<6.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", - "symfony/serializer": "<5.4", + "symfony/serializer": "<6.4", "symfony/stopwatch": "<5.4", - "symfony/translation": "<5.4", + "symfony/translation": "<6.4", "symfony/twig-bridge": "<5.4", "symfony/twig-bundle": "<5.4", - "symfony/validator": "<5.4", - "symfony/web-profiler-bundle": "<5.4", - "symfony/workflow": "<5.4" + "symfony/validator": "<6.4", + "symfony/web-profiler-bundle": "<6.4", + "symfony/workflow": "<6.4" }, "require-dev": { "doctrine/annotations": "^1.13.1|^2", "doctrine/persistence": "^1.3|^2|^3", + "dragonmantank/cron-expression": "^3.1", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/dotenv": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/mailer": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/notifier": "^5.4|^6.0", + "seld/jsonlint": "^1.10", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/html-sanitizer": "^6.1|^7.0", + "symfony/http-client": "^6.3|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/mailer": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.3|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/notifier": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/string": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/web-link": "^5.4|^6.0", - "symfony/workflow": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", - "twig/twig": "^2.10|^3.0" - }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/property-info": "For using the property_info service", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", - "symfony/yaml": "For using the debug:config and lint:yaml commands" + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", + "symfony/security-bundle": "^5.4|^6.0|^7.0", + "symfony/semaphore": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/string": "^5.4|^6.0|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0", + "twig/twig": "^2.10|^3.0.4" }, "type": "symfony-bundle", "autoload": { @@ -5219,7 +5612,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.0.19" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.17" }, "funding": [ { @@ -5235,27 +5628,32 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2024-12-19T14:08:41+00:00" }, { "name": "symfony/http-client", - "version": "v6.0.20", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "541c04560da1875f62c963c3aab6ea12a7314e11" + "reference": "88898d842eb29d7e1a903724c94e90a6ca9c0509" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/541c04560da1875f62c963c3aab6ea12a7314e11", - "reference": "541c04560da1875f62c963c3aab6ea12a7314e11", + "url": "https://api.github.com/repos/symfony/http-client/zipball/88898d842eb29d7e1a903724c94e90a6ca9c0509", + "reference": "88898d842eb29d7e1a903724c94e90a6ca9c0509", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/http-client-contracts": "^3", - "symfony/service-contracts": "^1.0|^2|^3" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.3" }, "provide": { "php-http/async-client-implementation": "*", @@ -5268,14 +5666,15 @@ "amphp/http-client": "^4.2.1", "amphp/http-tunnel": "^1.0", "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4", + "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5302,8 +5701,11 @@ ], "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", + "keywords": [ + "http" + ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.0.20" + "source": "https://github.com/symfony/http-client/tree/v6.4.17" }, "funding": [ { @@ -5319,20 +5721,20 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:41:07+00:00" + "time": "2024-12-18T12:18:31+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.4.2", + "version": "v3.5.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e" + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e", - "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", + "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", "shasum": "" }, "require": { @@ -5340,12 +5742,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -5381,7 +5783,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" }, "funding": [ { @@ -5397,40 +5799,41 @@ "type": "tidelift" } ], - "time": "2024-04-01T18:51:09+00:00" + "time": "2024-12-07T08:49:48+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.7", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759" + "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b4db6b833035477cb70e18d0ae33cb7c2b521759", - "reference": "b4db6b833035477cb70e18d0ae33cb7c2b521759", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62d1a43796ca3fea3f83a8470dfe63a4af3bc588", + "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3|^4", + "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/rate-limiter": "^5.4|^6.0|^7.0" + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5458,7 +5861,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.7" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.2" }, "funding": [ { @@ -5474,28 +5877,29 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.1.12", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "7a4a69dee1b0db04bdc12e86d4cd0dbf6daa390c" + "reference": "c5647393c5ce11833d13e4b70fff4b571d4ac710" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/7a4a69dee1b0db04bdc12e86d4cd0dbf6daa390c", - "reference": "7a4a69dee1b0db04bdc12e86d4cd0dbf6daa390c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c5647393c5ce11833d13e4b70fff4b571d4ac710", + "reference": "c5647393c5ce11833d13e4b70fff4b571d4ac710", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/error-handler": "^6.1", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -5503,15 +5907,18 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.1", + "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/mailer": "<5.4", "symfony/messenger": "<5.4", "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, "provide": { @@ -5519,29 +5926,29 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^6.1", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.1", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "symfony/uid": "^5.4|^6.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, "type": "library", "autoload": { "psr-4": { @@ -5568,7 +5975,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.1.12" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.17" }, "funding": [ { @@ -5584,27 +5991,29 @@ "type": "tidelift" } ], - "time": "2023-02-01T08:26:56+00:00" + "time": "2024-12-31T14:49:31+00:00" }, { "name": "symfony/intl", - "version": "v6.0.19", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "a2e1ce9048ea549ee1e8d9ce521cbe9a9ec7d92c" + "reference": "b1d5e8d82615b60f229216edfee0b59e2ef66da6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/a2e1ce9048ea549ee1e8d9ce521cbe9a9ec7d92c", - "reference": "a2e1ce9048ea549ee1e8d9ce521cbe9a9ec7d92c", + "url": "https://api.github.com/repos/symfony/intl/zipball/b1d5e8d82615b60f229216edfee0b59e2ef66da6", + "reference": "b1d5e8d82615b60f229216edfee0b59e2ef66da6", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0" + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5612,7 +6021,8 @@ "Symfony\\Component\\Intl\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/Resources/data/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5637,7 +6047,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a PHP replacement layer for the C intl extension that includes additional data from the ICU library", + "description": "Provides access to the localization data of the ICU library", "homepage": "https://symfony.com", "keywords": [ "i18n", @@ -5648,7 +6058,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.0.19" + "source": "https://github.com/symfony/intl/tree/v6.4.15" }, "funding": [ { @@ -5664,37 +6074,43 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-11-08T15:28:48+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "cd60799210c488f545ddde2444dc1aa548322872" + "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/cd60799210c488f545ddde2444dc1aa548322872", - "reference": "cd60799210c488f545ddde2444dc1aa548322872", + "url": "https://api.github.com/repos/symfony/mailer/zipball/c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", + "reference": "c2f7e0d8d7ac8fe25faccf5d8cac462805db2663", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/http-kernel": "<5.4" + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "require-dev": { - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.2|^7.0", + "symfony/twig-bridge": "^6.2|^7.0" }, "type": "library", "autoload": { @@ -5722,7 +6138,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.19" + "source": "https://github.com/symfony/mailer/tree/v6.4.13" }, "funding": [ { @@ -5738,48 +6154,50 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/messenger", - "version": "v6.0.19", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "d584d1754e9e19f83a43c75f36c84b42f6f7e209" + "reference": "b20092876c3d23c172a6469f9c0d7ef1de445257" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/d584d1754e9e19f83a43c75f36c84b42f6f7e209", - "reference": "d584d1754e9e19f83a43c75f36c84b42f6f7e209", + "url": "https://api.github.com/repos/symfony/messenger/zipball/b20092876c3d23c172a6469f9c0d7ef1de445257", + "reference": "b20092876c3d23c172a6469f9c0d7ef1de445257", "shasum": "" }, "require": { - "php": ">=8.0.2", - "psr/log": "^1|^2|^3" + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/clock": "^6.3|^7.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { + "symfony/console": "<6.3", "symfony/event-dispatcher": "<5.4", + "symfony/event-dispatcher-contracts": "<2.5", "symfony/framework-bundle": "<5.4", "symfony/http-kernel": "<5.4", "symfony/serializer": "<5.4" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0" - }, - "suggest": { - "enqueue/messenger-adapter": "For using the php-enqueue library as a transport." + "symfony/console": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/validator": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -5807,7 +6225,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v6.0.19" + "source": "https://github.com/symfony/messenger/tree/v6.4.16" }, "funding": [ { @@ -5823,24 +6241,24 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-11-25T02:02:03+00:00" }, { "name": "symfony/mime", - "version": "v6.1.11", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2bff58573e81a1df51bf99ad01725428beda1cbc" + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2bff58573e81a1df51bf99ad01725428beda1cbc", - "reference": "2bff58573e81a1df51bf99ad01725428beda1cbc", + "url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283", + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -5848,15 +6266,18 @@ "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<5.4" + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^5.2|^6.0" + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", "autoload": { @@ -5888,7 +6309,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.1.11" + "source": "https://github.com/symfony/mime/tree/v7.2.1" }, "funding": [ { @@ -5904,42 +6325,41 @@ "type": "tidelift" } ], - "time": "2023-01-10T18:53:01+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "ab1d73cecf06b02bbec65cf2e41196f36eda428c" + "reference": "bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/ab1d73cecf06b02bbec65cf2e41196f36eda428c", - "reference": "ab1d73cecf06b02bbec65cf2e41196f36eda428c", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d", + "reference": "bbae784f0456c5a87c89d7c1a3fcc9cbee976c1d", "shasum": "" }, "require": { - "monolog/monolog": "^1.25.1|^2|^3", - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^5.4|^6.0|^7.0", + "monolog/monolog": "^3", + "php": ">=8.2", + "symfony/http-kernel": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/console": "<5.4", - "symfony/http-foundation": "<5.4", - "symfony/security-core": "<5.4" + "symfony/console": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/security-core": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/mailer": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/mime": "^5.4|^6.0|^7.0", - "symfony/security-core": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/mailer": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "symfony-bridge", "autoload": { @@ -5967,7 +6387,7 @@ "description": "Provides integration for Monolog with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.7" + "source": "https://github.com/symfony/monolog-bridge/tree/v7.2.0" }, "funding": [ { @@ -5983,7 +6403,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-10-14T18:16:08+00:00" }, { "name": "symfony/monolog-bundle", @@ -6068,30 +6488,33 @@ }, { "name": "symfony/notifier", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/notifier.git", - "reference": "99566882d0dee350a1434be4baa50585db0d6539" + "reference": "c46321b53391088861bf627cd9e24873d216cf00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/notifier/zipball/99566882d0dee350a1434be4baa50585db0d6539", - "reference": "99566882d0dee350a1434be4baa50585db0d6539", + "url": "https://api.github.com/repos/symfony/notifier/zipball/c46321b53391088861bf627cd9e24873d216cf00", + "reference": "c46321b53391088861bf627cd9e24873d216cf00", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3" }, "conflict": { "symfony/event-dispatcher": "<5.4", + "symfony/event-dispatcher-contracts": "<2.5", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4" }, "require-dev": { - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/http-client-contracts": "^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/event-dispatcher-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -6123,7 +6546,7 @@ "notifier" ], "support": { - "source": "https://github.com/symfony/notifier/tree/v6.0.19" + "source": "https://github.com/symfony/notifier/tree/v6.4.13" }, "funding": [ { @@ -6139,24 +6562,24 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/9a3c92b490716ba6771f5beced13c6eda7183eed", - "reference": "9a3c92b490716ba6771f5beced13c6eda7183eed", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -6190,7 +6613,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.7" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -6206,31 +6629,31 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "73afaed1d87f6127dcd71bc88e9a16fd9325cf1c" + "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/73afaed1d87f6127dcd71bc88e9a16fd9325cf1c", - "reference": "73afaed1d87f6127dcd71bc88e9a16fd9325cf1c", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", + "reference": "d8bd3d66d074c0acba1214a0d42f5941a8e1e94d", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "conflict": { - "symfony/security-core": "<5.4" + "symfony/security-core": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/security-core": "^5.4|^6.0|^7.0" + "symfony/console": "^6.4|^7.0", + "symfony/security-core": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6262,7 +6685,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.7" + "source": "https://github.com/symfony/password-hasher/tree/v7.2.0" }, "funding": [ { @@ -6278,24 +6701,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -6303,8 +6726,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6340,7 +6763,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -6356,24 +6779,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1" + "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/07094a28851a49107f3ab4f9120ca2975a64b6e1", - "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", + "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance and support of other locales than \"en\"" @@ -6381,8 +6804,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6424,7 +6847,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.31.0" }, "funding": [ { @@ -6440,26 +6863,25 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:12:16+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "a287ed7475f85bf6f61890146edbc932c0fff919" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", - "reference": "a287ed7475f85bf6f61890146edbc932c0fff919", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" @@ -6467,8 +6889,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6508,7 +6930,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -6524,24 +6946,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" @@ -6549,8 +6971,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6589,7 +7011,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -6605,24 +7027,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -6633,8 +7055,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6669,7 +7091,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -6685,30 +7107,30 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6749,7 +7171,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -6765,30 +7187,30 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d" + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d", - "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6825,7 +7247,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" }, "funding": [ { @@ -6841,31 +7263,30 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "86fcae159633351e5fd145d1c47de6c528f8caff" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff", - "reference": "86fcae159633351e5fd145d1c47de6c528f8caff", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-php80": "^1.14" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6902,7 +7323,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -6918,24 +7339,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.29.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853" + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853", - "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -6946,8 +7367,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -6981,7 +7402,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" }, "funding": [ { @@ -6997,24 +7418,24 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v6.0.19", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "2114fd60f26a296cc403a7939ab91478475a33d4" + "reference": "3cb242f059c14ae08591c5c4087d1fe443564392" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/2114fd60f26a296cc403a7939ab91478475a33d4", - "reference": "2114fd60f26a296cc403a7939ab91478475a33d4", + "url": "https://api.github.com/repos/symfony/process/zipball/3cb242f059c14ae08591c5c4087d1fe443564392", + "reference": "3cb242f059c14ae08591c5c4087d1fe443564392", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -7042,7 +7463,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.19" + "source": "https://github.com/symfony/process/tree/v6.4.15" }, "funding": [ { @@ -7058,31 +7479,29 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-11-06T14:19:14+00:00" }, { "name": "symfony/property-access", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "cae9aadf6e3a08315af666d4fede905fbb5b5393" + "reference": "8cc779d88d12e440adaa26387bcfc25744064afe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/cae9aadf6e3a08315af666d4fede905fbb5b5393", - "reference": "cae9aadf6e3a08315af666d4fede905fbb5b5393", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8cc779d88d12e440adaa26387bcfc25744064afe", + "reference": "8cc779d88d12e440adaa26387bcfc25744064afe", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/property-info": "^5.4|^6.0" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/property-info": "^5.4|^6.0|^7.0" }, "require-dev": { - "symfony/cache": "^5.4|^6.0" - }, - "suggest": { - "psr/cache-implementation": "To cache access methods." + "symfony/cache": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7117,11 +7536,11 @@ "injection", "object", "property", - "property path", + "property-path", "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.0.19" + "source": "https://github.com/symfony/property-access/tree/v6.4.13" }, "funding": [ { @@ -7137,44 +7556,39 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/property-info", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "e6dfb2223b21768d3b2ae033a5e1f9d205184d45" + "reference": "38b125d78e67668159f75383a293ec0c5d3f2963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/e6dfb2223b21768d3b2ae033a5e1f9d205184d45", - "reference": "e6dfb2223b21768d3b2ae033a5e1f9d205184d45", + "url": "https://api.github.com/repos/symfony/property-info/zipball/38b125d78e67668159f75383a293ec0c5d3f2963", + "reference": "38b125d78e67668159f75383a293ec0c5d3f2963", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/string": "^5.4|^6.0" + "php": ">=8.1", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { + "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<5.4" + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<5.4|>=6.0,<6.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" - }, - "suggest": { - "phpdocumentor/reflection-docblock": "To use the PHPDoc", - "psr/cache-implementation": "To cache results", - "symfony/doctrine-bridge": "To use Doctrine metadata", - "symfony/serializer": "To use Serializer metadata" + "doctrine/annotations": "^1.12|^2", + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -7210,7 +7624,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.0.19" + "source": "https://github.com/symfony/property-info/tree/v6.4.17" }, "funding": [ { @@ -7226,29 +7640,30 @@ "type": "tidelift" } ], - "time": "2023-01-15T17:21:41+00:00" + "time": "2024-12-26T19:01:29+00:00" }, { "name": "symfony/proxy-manager-bridge", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", - "reference": "905733405585e584596a2ea2874dad84a738daa8" + "reference": "8932b572e147e80fb498045c580eb14215197529" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/905733405585e584596a2ea2874dad84a738daa8", - "reference": "905733405585e584596a2ea2874dad84a738daa8", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/8932b572e147e80fb498045c580eb14215197529", + "reference": "8932b572e147e80fb498045c580eb14215197529", "shasum": "" }, "require": { "friendsofphp/proxy-manager-lts": "^1.0.2", - "php": ">=8.0.2", - "symfony/dependency-injection": "^5.4|^6.0" + "php": ">=8.1", + "symfony/dependency-injection": "^6.3|^7.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/config": "^5.4|^6.0" + "symfony/config": "^6.1|^7.0" }, "type": "symfony-bridge", "autoload": { @@ -7276,7 +7691,7 @@ "description": "Provides integration for ProxyManager with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.0.19" + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.13" }, "funding": [ { @@ -7292,40 +7707,38 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/routing", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "276e06398f71fa2a973264d94f28150f93cfb907" + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/276e06398f71fa2a973264d94f28150f93cfb907", - "reference": "276e06398f71fa2a973264d94f28150f93cfb907", + "url": "https://api.github.com/repos/symfony/routing/zipball/e10a2450fa957af6c448b9b93c9010a4e4c0725e", + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/yaml": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7359,7 +7772,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.7" + "source": "https://github.com/symfony/routing/tree/v7.2.0" }, "funding": [ { @@ -7375,63 +7788,75 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-25T11:08:51+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.0.20", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "fbe14faff3dbae154d0004b254a201e930f3d8e0" + "reference": "181d1fcf5f88ef8212ed7f6434e5ff51c9d7dff3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/fbe14faff3dbae154d0004b254a201e930f3d8e0", - "reference": "fbe14faff3dbae154d0004b254a201e930f3d8e0", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/181d1fcf5f88ef8212ed7f6434e5ff51c9d7dff3", + "reference": "181d1fcf5f88ef8212ed7f6434e5ff51c9d7dff3", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.0.2", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/password-hasher": "^5.4|^6.0", - "symfony/security-core": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^5.4.20|~6.0.20|~6.1.12|^6.2.6" + "php": ">=8.1", + "symfony/clock": "^6.3|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/dependency-injection": "^6.4.11|^7.1.4", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.2|^7.0", + "symfony/http-kernel": "^6.2", + "symfony/password-hasher": "^5.4|^6.0|^7.0", + "symfony/security-core": "^6.2|^7.0", + "symfony/security-csrf": "^5.4|^6.0|^7.0", + "symfony/security-http": "^6.3.6|^7.0", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { "symfony/browser-kit": "<5.4", "symfony/console": "<5.4", - "symfony/framework-bundle": "<5.4", + "symfony/framework-bundle": "<6.4", + "symfony/http-client": "<5.4", "symfony/ldap": "<5.4", - "symfony/twig-bundle": "<5.4" + "symfony/serializer": "<6.4", + "symfony/twig-bundle": "<5.4", + "symfony/validator": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "symfony/asset": "^5.4|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0", - "symfony/ldap": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/twig-bridge": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/ldap": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4", + "web-token/jwt-checker": "^3.1", + "web-token/jwt-signature-algorithm-ecdsa": "^3.1", + "web-token/jwt-signature-algorithm-eddsa": "^3.1", + "web-token/jwt-signature-algorithm-hmac": "^3.1", + "web-token/jwt-signature-algorithm-none": "^3.1", + "web-token/jwt-signature-algorithm-rsa": "^3.1" }, "type": "symfony-bundle", "autoload": { @@ -7459,7 +7884,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.0.20" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.13" }, "funding": [ { @@ -7475,47 +7900,49 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:41:07+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.0", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "9e24a7199744d944c03fc1448276dc57f6237a33" + "reference": "fdbf318b939a86f89b0c071f60b9d551261d3cc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/9e24a7199744d944c03fc1448276dc57f6237a33", - "reference": "9e24a7199744d944c03fc1448276dc57f6237a33", + "url": "https://api.github.com/repos/symfony/security-core/zipball/fdbf318b939a86f89b0c071f60b9d551261d3cc1", + "reference": "fdbf318b939a86f89b0c071f60b9d551261d3cc1", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher-contracts": "^2.5|^3", - "symfony/password-hasher": "^5.4|^6.0|^7.0", + "symfony/password-hasher": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/event-dispatcher": "<5.4", - "symfony/http-foundation": "<5.4", - "symfony/ldap": "<5.4", - "symfony/security-guard": "<5.4", - "symfony/validator": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/http-foundation": "<6.4", + "symfony/ldap": "<6.4", + "symfony/translation": "<6.4.3|>=7.0,<7.0.3", + "symfony/validator": "<6.4" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "psr/container": "^1.1|^2.0", "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", - "symfony/ldap": "^5.4|^6.0|^7.0", - "symfony/string": "^5.4|^6.0|^7.0", - "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/cache": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/ldap": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", + "symfony/translation": "^6.4.3|^7.0.3", "symfony/validator": "^6.4|^7.0" }, "type": "library", @@ -7544,7 +7971,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.0" + "source": "https://github.com/symfony/security-core/tree/v7.2.0" }, "funding": [ { @@ -7560,31 +7987,33 @@ "type": "tidelift" } ], - "time": "2023-11-06T17:20:05+00:00" + "time": "2024-11-27T09:50:52+00:00" }, { "name": "symfony/security-csrf", - "version": "v6.4.7", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "91fe7e829a8fe1e78bd3615c7a410dce6876325b" + "reference": "a2031e57dc02002163770a5cc02fafdd70decf1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/91fe7e829a8fe1e78bd3615c7a410dce6876325b", - "reference": "91fe7e829a8fe1e78bd3615c7a410dce6876325b", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/a2031e57dc02002163770a5cc02fafdd70decf1d", + "reference": "a2031e57dc02002163770a5cc02fafdd70decf1d", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/security-core": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/security-core": "^6.4|^7.0" }, "conflict": { - "symfony/http-foundation": "<5.4" + "symfony/http-foundation": "<6.4" }, "require-dev": { - "symfony/http-foundation": "^5.4|^6.0|^7.0" + "psr/log": "^1|^2|^3", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7612,7 +8041,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.4.7" + "source": "https://github.com/symfony/security-csrf/tree/v7.2.2" }, "funding": [ { @@ -7628,46 +8057,51 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-12-20T09:56:48+00:00" }, { "name": "symfony/security-http", - "version": "v6.1.12", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "e671c9748c439492c4a2d07862ee63a9a6fbf5c1" + "reference": "125844598d9cef4fe72a9f6c4a78ac7c59c3f532" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/e671c9748c439492c4a2d07862ee63a9a6fbf5c1", - "reference": "e671c9748c439492c4a2d07862ee63a9a6fbf5c1", + "url": "https://api.github.com/repos/symfony/security-http/zipball/125844598d9cef4fe72a9f6c4a78ac7c59c3f532", + "reference": "125844598d9cef4fe72a9f6c4a78ac7c59c3f532", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^6.1", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/security-core": "^5.4.19|~6.0.19|~6.1.11|^6.2.5" + "symfony/property-access": "^6.4|^7.0", + "symfony/security-core": "^7.2", + "symfony/service-contracts": "^2.5|^3" }, "conflict": { - "symfony/event-dispatcher": "<5.4.9|>=6,<6.0.9", - "symfony/security-bundle": "<5.4", - "symfony/security-csrf": "<5.4" + "symfony/clock": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/http-client-contracts": "<3.0", + "symfony/security-bundle": "<6.4", + "symfony/security-csrf": "<6.4" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/cache": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0" - }, - "suggest": { - "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", - "symfony/security-csrf": "For using tokens to protect authentication/logout attempts" + "symfony/cache": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/http-client-contracts": "^3.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/security-csrf": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "web-token/jwt-library": "^3.3.2|^4.0" }, "type": "library", "autoload": { @@ -7695,7 +8129,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.1.12" + "source": "https://github.com/symfony/security-http/tree/v7.2.1" }, "funding": [ { @@ -7711,24 +8145,25 @@ "type": "tidelift" } ], - "time": "2023-01-30T15:43:30+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/serializer", - "version": "v6.0.14", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "d3bea0f239aca9589224a84150066da5495e9e11" + "reference": "9d862d66198f3c2e30404228629ef4c18d5d608e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/d3bea0f239aca9589224a84150066da5495e9e11", - "reference": "d3bea0f239aca9589224a84150066da5495e9e11", + "url": "https://api.github.com/repos/symfony/serializer/zipball/9d862d66198f3c2e30404228629ef4c18d5d608e", + "reference": "9d862d66198f3c2e30404228629ef4c18d5d608e", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -7737,38 +8172,34 @@ "phpdocumentor/type-resolver": "<1.4.0", "symfony/dependency-injection": "<5.4", "symfony/property-access": "<5.4", - "symfony/property-info": "<5.4", + "symfony/property-info": "<5.4.24|>=6,<6.2.11", "symfony/uid": "<5.4", + "symfony/validator": "<6.4", "symfony/yaml": "<5.4" }, "require-dev": { - "doctrine/annotations": "^1.12", + "doctrine/annotations": "^1.12|^2", "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0", - "symfony/var-exporter": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "psr/cache-implementation": "For using the metadata cache.", - "symfony/config": "For using the XML mapping loader.", - "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", - "symfony/property-access": "For using the ObjectNormalizer.", - "symfony/property-info": "To deserialize relations.", - "symfony/var-exporter": "For using the metadata compiler.", - "symfony/yaml": "For using the default YAML mapping loader." + "seld/jsonlint": "^1.10", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.26|^6.3|^7.0", + "symfony/property-info": "^5.4.24|^6.2.11|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -7796,7 +8227,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.0.14" + "source": "https://github.com/symfony/serializer/tree/v6.4.15" }, "funding": [ { @@ -7812,37 +8243,38 @@ "type": "tidelift" } ], - "time": "2022-10-11T15:20:43+00:00" + "time": "2024-10-23T13:25:59+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", - "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -7878,7 +8310,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -7894,25 +8326,25 @@ "type": "tidelift" } ], - "time": "2023-12-19T21:51:00+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "011e781839dd1d2eb8119f65ac516a530f60226d" + "reference": "2cae0a6f8d04937d02f6d19806251e2104d54f92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/011e781839dd1d2eb8119f65ac516a530f60226d", - "reference": "011e781839dd1d2eb8119f65ac516a530f60226d", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/2cae0a6f8d04937d02f6d19806251e2104d54f92", + "reference": "2cae0a6f8d04937d02f6d19806251e2104d54f92", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/service-contracts": "^1|^2|^3" + "php": ">=8.1", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -7940,7 +8372,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.0.19" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.13" }, "funding": [ { @@ -7956,37 +8388,38 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/string", - "version": "v6.0.19", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -8025,7 +8458,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.19" + "source": "https://github.com/symfony/string/tree/v6.4.15" }, "funding": [ { @@ -8041,32 +8474,35 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-11-13T13:31:12+00:00" }, { "name": "symfony/translation", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", - "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "url": "https://api.github.com/repos/symfony/translation/zipball/bee9bfabfa8b4045a66bf82520e492cddbaffa66", + "reference": "bee9bfabfa8b4045a66bf82520e492cddbaffa66", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "symfony/config": "<5.4", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", "symfony/twig-bundle": "<5.4", "symfony/yaml": "<5.4" }, @@ -8074,22 +8510,19 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -8120,7 +8553,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.19" + "source": "https://github.com/symfony/translation/tree/v6.4.13" }, "funding": [ { @@ -8136,20 +8569,20 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-27T18:14:25+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/43810bdb2ddb5400e5c5e778e27b210a0ca83b6b", - "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { @@ -8157,12 +8590,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" } }, "autoload": { @@ -8198,7 +8631,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -8214,84 +8647,73 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "bcd79f7845f887defec9d6737a535a3c602159e9" + "reference": "238e1aac992b5231c66faf10131ace7bdba97065" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/bcd79f7845f887defec9d6737a535a3c602159e9", - "reference": "bcd79f7845f887defec9d6737a535a3c602159e9", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/238e1aac992b5231c66faf10131ace7bdba97065", + "reference": "238e1aac992b5231c66faf10131ace7bdba97065", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/translation-contracts": "^1.1|^2|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/translation-contracts": "^2.5|^3", "twig/twig": "^2.13|^3.0.4" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/console": "<5.4", - "symfony/form": "<5.4", + "symfony/form": "<6.3", "symfony/http-foundation": "<5.4", - "symfony/http-kernel": "<5.4", + "symfony/http-kernel": "<6.4", + "symfony/mime": "<6.2", + "symfony/serializer": "<6.4", "symfony/translation": "<5.4", "symfony/workflow": "<5.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "egulias/email-validator": "^2.1.10|^3|^4", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/asset-mapper": "^6.3|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/form": "^6.4|^7.0", + "symfony/html-sanitizer": "^6.1|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/mime": "^6.2|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", "symfony/security-acl": "^2.8|^3.0", - "symfony/security-core": "^5.4|^6.0", - "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/web-link": "^5.4|^6.0", - "symfony/workflow": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/security-csrf": "^5.4|^6.0|^7.0", + "symfony/security-http": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^6.1|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/workflow": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0", "twig/cssinliner-extra": "^2.12|^3", "twig/inky-extra": "^2.12|^3", "twig/markdown-extra": "^2.12|^3" }, - "suggest": { - "symfony/asset": "For using the AssetExtension", - "symfony/expression-language": "For using the ExpressionExtension", - "symfony/finder": "", - "symfony/form": "For using the FormExtension", - "symfony/http-kernel": "For using the HttpKernelExtension", - "symfony/routing": "For using the RoutingExtension", - "symfony/security-core": "For using the SecurityExtension", - "symfony/security-csrf": "For using the CsrfExtension", - "symfony/security-http": "For using the LogoutUrlExtension", - "symfony/stopwatch": "For using the StopwatchExtension", - "symfony/translation": "For using the TranslationExtension", - "symfony/var-dumper": "For using the DumpExtension", - "symfony/web-link": "For using the WebLinkExtension", - "symfony/yaml": "For using the YamlExtension" - }, "type": "symfony-bridge", "autoload": { "psr-4": { @@ -8318,7 +8740,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.0.19" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.17" }, "funding": [ { @@ -8334,50 +8756,47 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2024-12-19T14:08:41+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "13ce8cae82ca5870aabfcfd2e8d4bd03d3d843d5" + "reference": "c3beeb5336aba1ea03c37e526968c2fde3ef25c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/13ce8cae82ca5870aabfcfd2e8d4bd03d3d843d5", - "reference": "13ce8cae82ca5870aabfcfd2e8d4bd03d3d843d5", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/c3beeb5336aba1ea03c37e526968c2fde3ef25c4", + "reference": "c3beeb5336aba1ea03c37e526968c2fde3ef25c4", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", - "php": ">=8.0.2", - "symfony/config": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/twig-bridge": "^5.4|^6.0", + "php": ">=8.1", + "symfony/config": "^6.1|^7.0", + "symfony/dependency-injection": "^6.1|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^6.2", + "symfony/twig-bridge": "^6.4", "twig/twig": "^2.13|^3.0.4" }, "conflict": { - "symfony/dependency-injection": "<5.4", "symfony/framework-bundle": "<5.4", "symfony/translation": "<5.4" }, "require-dev": { - "doctrine/annotations": "^1.10.4|^2", - "symfony/asset": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/web-link": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -8405,7 +8824,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.0.19" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.13" }, "funding": [ { @@ -8421,28 +8840,28 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/uid", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d" + "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", - "reference": "6499e28b0ac9f2aa3151e11845bdb5cd21e6bb9d", + "url": "https://api.github.com/repos/symfony/uid/zipball/18eb207f0436a993fffbdd811b5b8fa35fa5e007", + "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -8479,7 +8898,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.0.19" + "source": "https://github.com/symfony/uid/tree/v6.4.13" }, "funding": [ { @@ -8495,71 +8914,59 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/validator", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "8e41a2dc215903964175ca8bdc884297f021d31c" + "reference": "a3c19a0e542d427c207e22242043ef35b5b99a2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/8e41a2dc215903964175ca8bdc884297f021d31c", - "reference": "8e41a2dc215903964175ca8bdc884297f021d31c", + "url": "https://api.github.com/repos/symfony/validator/zipball/a3c19a0e542d427c207e22242043ef35b5b99a2c", + "reference": "a3c19a0e542d427c207e22242043ef35b5b99a2c", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php81": "^1.22", - "symfony/translation-contracts": "^1.1|^2|^3" + "symfony/polyfill-php83": "^1.27", + "symfony/translation-contracts": "^2.5|^3" }, "conflict": { "doctrine/annotations": "<1.13", "doctrine/lexer": "<1.1", - "phpunit/phpunit": "<5.4.3", "symfony/dependency-injection": "<5.4", "symfony/expression-language": "<5.4", "symfony/http-kernel": "<5.4", "symfony/intl": "<5.4", "symfony/property-info": "<5.4", - "symfony/translation": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.13|^2", "egulias/email-validator": "^2.1.10|^3|^4", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "egulias/email-validator": "Strict (RFC compliant) email validation", - "psr/cache-implementation": "For using the mapping cache.", - "symfony/config": "", - "symfony/expression-language": "For using the Expression validator and the ExpressionLanguageSyntax constraints", - "symfony/http-foundation": "", - "symfony/intl": "", - "symfony/property-access": "For accessing properties within comparison constraints", - "symfony/property-info": "To automatically add NotNull and Type constraints", - "symfony/translation": "For translating validation errors.", - "symfony/yaml": "" + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -8567,7 +8974,8 @@ "Symfony\\Component\\Validator\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/Resources/bin/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -8587,7 +8995,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.0.19" + "source": "https://github.com/symfony/validator/tree/v6.4.17" }, "funding": [ { @@ -8603,38 +9011,36 @@ "type": "tidelift" } ], - "time": "2023-01-15T17:21:41+00:00" + "time": "2024-12-29T12:50:19+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7" + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7a9cd977cd1c5fed3694bee52990866432af07d7", - "reference": "7a9cd977cd1c5fed3694bee52990866432af07d7", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -8672,7 +9078,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.7" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" }, "funding": [ { @@ -8688,20 +9094,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-08T15:48:14+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.0.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078" + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/cdecc0022e40e90340ba1a59a3d5ccf069777078", - "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1a6a89f95a46af0f142874c9d650a6358d13070d", + "reference": "1a6a89f95a46af0f142874c9d650a6358d13070d", "shasum": "" }, "require": { @@ -8748,7 +9154,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.7" + "source": "https://github.com/symfony/var-exporter/tree/v7.2.0" }, "funding": [ { @@ -8764,24 +9170,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:29:19+00:00" + "time": "2024-10-18T07:58:17+00:00" }, { "name": "symfony/web-link", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "65cbc32c8177cfec22afde261e54533c408e5fa0" + "reference": "4d188b64bb9a9c5e2e4d20c8d5fdce6bbbb32c94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/65cbc32c8177cfec22afde261e54533c408e5fa0", - "reference": "65cbc32c8177cfec22afde261e54533c408e5fa0", + "url": "https://api.github.com/repos/symfony/web-link/zipball/4d188b64bb9a9c5e2e4d20c8d5fdce6bbbb32c94", + "reference": "4d188b64bb9a9c5e2e4d20c8d5fdce6bbbb32c94", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/link": "^1.1|^2.0" }, "conflict": { @@ -8791,10 +9197,7 @@ "psr/link-implementation": "1.0|2.0" }, "require-dev": { - "symfony/http-kernel": "^5.4|^6.0" - }, - "suggest": { - "symfony/http-kernel": "" + "symfony/http-kernel": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -8834,7 +9237,7 @@ "push" ], "support": { - "source": "https://github.com/symfony/web-link/tree/v6.0.19" + "source": "https://github.com/symfony/web-link/tree/v6.4.13" }, "funding": [ { @@ -8850,7 +9253,7 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/webpack-encore-bundle", @@ -8885,8 +9288,8 @@ "type": "symfony-bundle", "extra": { "thanks": { - "name": "symfony/webpack-encore", - "url": "https://github.com/symfony/webpack-encore" + "url": "https://github.com/symfony/webpack-encore", + "name": "symfony/webpack-encore" } }, "autoload": { @@ -8927,30 +9330,28 @@ }, { "name": "symfony/yaml", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "deec3a812a0305a50db8ae689b183f43d915c884" + "reference": "e99b4e94d124b29ee4cf3140e1b537d2dad8cec9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/deec3a812a0305a50db8ae689b183f43d915c884", - "reference": "deec3a812a0305a50db8ae689b183f43d915c884", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e99b4e94d124b29ee4cf3140e1b537d2dad8cec9", + "reference": "e99b4e94d124b29ee4cf3140e1b537d2dad8cec9", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -8981,7 +9382,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.0.19" + "source": "https://github.com/symfony/yaml/tree/v6.4.13" }, "funding": [ { @@ -8997,38 +9398,38 @@ "type": "tidelift" } ], - "time": "2023-01-11T11:50:03+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "twig/extra-bundle", - "version": "v3.8.0", + "version": "v3.18.0", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140" + "reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/32807183753de0388c8e59f7ac2d13bb47311140", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9746573ca4bc1cd03a767a183faadaf84e0c31fa", + "reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/framework-bundle": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", - "twig/twig": "^3.0" + "php": ">=8.0.2", + "symfony/framework-bundle": "^5.4|^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.4|^7.0", + "twig/twig": "^3.2|^4.0" }, "require-dev": { "league/commonmark": "^1.0|^2.0", "symfony/phpunit-bridge": "^6.4|^7.0", "twig/cache-extra": "^3.0", - "twig/cssinliner-extra": "^2.12|^3.0", - "twig/html-extra": "^2.12|^3.0", - "twig/inky-extra": "^2.12|^3.0", - "twig/intl-extra": "^2.12|^3.0", - "twig/markdown-extra": "^2.12|^3.0", - "twig/string-extra": "^2.12|^3.0" + "twig/cssinliner-extra": "^3.0", + "twig/html-extra": "^3.0", + "twig/inky-extra": "^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.0", + "twig/string-extra": "^3.0" }, "type": "symfony-bundle", "autoload": { @@ -9059,7 +9460,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.8.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.18.0" }, "funding": [ { @@ -9071,30 +9472,31 @@ "type": "tidelift" } ], - "time": "2023-11-21T14:02:01+00:00" + "time": "2024-09-26T19:22:23+00:00" }, { "name": "twig/twig", - "version": "v3.9.3", + "version": "v3.18.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58" + "reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", - "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", + "reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.0.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22" + "symfony/polyfill-php81": "^1.29" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -9138,7 +9540,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.9.3" + "source": "https://github.com/twigphp/Twig/tree/v3.18.0" }, "funding": [ { @@ -9150,7 +9552,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T11:59:33+00:00" + "time": "2024-12-29T10:51:50+00:00" }, { "name": "ucfopen/phpally", @@ -9267,22 +9669,22 @@ "packages-dev": [ { "name": "doctrine/data-fixtures", - "version": "1.7.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "bbcb74f2ac6dbe81a14b3c3687d7623490a0448f" + "reference": "2ae45139f148c9272c49a521d82cc50491355a99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/bbcb74f2ac6dbe81a14b3c3687d7623490a0448f", - "reference": "bbcb74f2ac6dbe81a14b3c3687d7623490a0448f", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/2ae45139f148c9272c49a521d82cc50491355a99", + "reference": "2ae45139f148c9272c49a521d82cc50491355a99", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1.0", - "doctrine/persistence": "^2.0|^3.0", - "php": "^7.4 || ^8.0" + "doctrine/persistence": "^3.1", + "php": "^8.1", + "psr/log": "^1.1 || ^2 || ^3" }, "conflict": { "doctrine/dbal": "<3.5 || >=5", @@ -9290,17 +9692,16 @@ "doctrine/phpcr-odm": "<1.3.0" }, "require-dev": { - "doctrine/annotations": "^1.12 || ^2", "doctrine/coding-standard": "^12", "doctrine/dbal": "^3.5 || ^4", "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", "doctrine/orm": "^2.14 || ^3", "ext-sqlite3": "*", + "fig/log-test": "^1", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6.13 || ^10.4.2", - "symfony/cache": "^5.4 || ^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6.3 || ^7", - "vimeo/psalm": "^5.9" + "phpunit/phpunit": "^10.5.3", + "symfony/cache": "^6.4 || ^7", + "symfony/var-exporter": "^6.4 || ^7" }, "suggest": { "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", @@ -9331,7 +9732,7 @@ ], "support": { "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.7.0" + "source": "https://github.com/doctrine/data-fixtures/tree/2.0.1" }, "funding": [ { @@ -9347,49 +9748,49 @@ "type": "tidelift" } ], - "time": "2023-11-24T11:18:31+00:00" + "time": "2024-12-10T07:03:23+00:00" }, { "name": "doctrine/doctrine-fixtures-bundle", - "version": "3.5.1", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", - "reference": "c808a0c85c38c8ee265cc8405b456c1d2b38567d" + "reference": "bd59519a7532b9e1a41cef4049d5326dfac7def9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/c808a0c85c38c8ee265cc8405b456c1d2b38567d", - "reference": "c808a0c85c38c8ee265cc8405b456c1d2b38567d", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/bd59519a7532b9e1a41cef4049d5326dfac7def9", + "reference": "bd59519a7532b9e1a41cef4049d5326dfac7def9", "shasum": "" }, "require": { - "doctrine/data-fixtures": "^1.3", + "doctrine/data-fixtures": "^1.5 || ^2.0", "doctrine/doctrine-bundle": "^2.2", "doctrine/orm": "^2.14.0 || ^3.0", - "doctrine/persistence": "^2.4|^3.0", + "doctrine/persistence": "^2.4 || ^3.0", "php": "^7.4 || ^8.0", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/doctrine-bridge": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0" + "psr/log": "^1 || ^2 || ^3", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/doctrine-bridge": "^5.4.48 || ^6.4.16 || ^7.1.9", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0" }, "conflict": { "doctrine/dbal": "< 3" }, "require-dev": { "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10.39", + "phpstan/phpstan": "^2", "phpunit/phpunit": "^9.6.13", - "symfony/phpunit-bridge": "^6.3.6", - "vimeo/psalm": "^5.15" + "symfony/phpunit-bridge": "^6.3.6" }, "type": "symfony-bundle", "autoload": { "psr-4": { - "Doctrine\\Bundle\\FixturesBundle\\": "" + "Doctrine\\Bundle\\FixturesBundle\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -9418,7 +9819,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", - "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.5.1" + "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/3.7.1" }, "funding": [ { @@ -9434,7 +9835,7 @@ "type": "tidelift" } ], - "time": "2023-11-19T12:48:54+00:00" + "time": "2024-12-03T17:07:51+00:00" }, { "name": "masterminds/html5", @@ -9505,25 +9906,27 @@ }, { "name": "nikic/php-parser", - "version": "v4.19.1", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -9531,7 +9934,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -9555,9 +9958,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-03-17T08:10:35+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "phar-io/manifest", @@ -9677,37 +10080,89 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-cs-fixer/shim", + "version": "v3.68.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "23acc692a99304559d4c94e9f299158ecd0ed7d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/23acc692a99304559d4c94e9f299158ecd0ed7d1", + "reference": "23acc692a99304559d4c94e9f299158ecd0ed7d1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "replace": { + "friendsofphp/php-cs-fixer": "self.version" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer", + "php-cs-fixer.phar" + ], + "type": "application", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/PHP-CS-Fixer/shim/issues", + "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.68.0" + }, + "time": "2025-01-13T17:01:38+00:00" + }, { "name": "phpunit/php-code-coverage", - "version": "9.2.31", + "version": "9.2.32", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", - "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", + "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.18 || ^5.0", + "nikic/php-parser": "^4.19.1 || ^5.1.0", "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "phpunit/php-file-iterator": "^3.0.6", + "phpunit/php-text-template": "^2.0.4", + "sebastian/code-unit-reverse-lookup": "^2.0.3", + "sebastian/complexity": "^2.0.3", + "sebastian/environment": "^5.1.5", + "sebastian/lines-of-code": "^1.0.4", + "sebastian/version": "^3.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -9716,7 +10171,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "9.2.x-dev" } }, "autoload": { @@ -9745,7 +10200,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" }, "funding": [ { @@ -9753,7 +10208,7 @@ "type": "github" } ], - "time": "2024-03-02T06:37:42+00:00" + "time": "2024-08-22T04:23:01+00:00" }, { "name": "phpunit/php-file-iterator", @@ -9998,45 +10453,45 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.19", + "version": "9.6.22", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", - "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", + "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-code-coverage": "^9.2.32", + "phpunit/php-file-iterator": "^3.0.6", "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", + "phpunit/php-text-template": "^2.0.4", + "phpunit/php-timer": "^5.0.3", + "sebastian/cli-parser": "^1.0.2", + "sebastian/code-unit": "^1.0.8", "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", + "sebastian/diff": "^4.0.6", + "sebastian/environment": "^5.1.5", + "sebastian/exporter": "^4.0.6", + "sebastian/global-state": "^5.0.7", + "sebastian/object-enumerator": "^4.0.4", + "sebastian/resource-operations": "^3.0.4", + "sebastian/type": "^3.2.1", "sebastian/version": "^3.0.2" }, "suggest": { @@ -10081,7 +10536,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" }, "funding": [ { @@ -10097,7 +10552,7 @@ "type": "tidelift" } ], - "time": "2024-04-05T04:35:58+00:00" + "time": "2024-12-05T13:48:26+00:00" }, { "name": "sebastian/cli-parser", @@ -11064,30 +11519,27 @@ }, { "name": "symfony/browser-kit", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "4d1bf7886e2af0a194332486273debcd6662cfc9" + "reference": "65d4b3fd9556e4b5b41287bef93c671f8f9f86ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/4d1bf7886e2af0a194332486273debcd6662cfc9", - "reference": "4d1bf7886e2af0a194332486273debcd6662cfc9", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/65d4b3fd9556e4b5b41287bef93c671f8f9f86ab", + "reference": "65d4b3fd9556e4b5b41287bef93c671f8f9f86ab", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/dom-crawler": "^5.4|^6.0" + "php": ">=8.1", + "symfony/dom-crawler": "^5.4|^6.0|^7.0" }, "require-dev": { - "symfony/css-selector": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" - }, - "suggest": { - "symfony/process": "" + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -11115,7 +11567,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v6.0.19" + "source": "https://github.com/symfony/browser-kit/tree/v6.4.13" }, "funding": [ { @@ -11131,24 +11583,24 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/css-selector", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f1d00bddb83a4cb2138564b2150001cb6ce272b1", - "reference": "f1d00bddb83a4cb2138564b2150001cb6ce272b1", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -11180,7 +11632,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.0.19" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -11196,41 +11648,37 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/debug-bundle", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "9890e76f4b03d253327108fbf70b0465cee9f99c" + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/9890e76f4b03d253327108fbf70b0465cee9f99c", - "reference": "9890e76f4b03d253327108fbf70b0465cee9f99c", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/7bcfaff39e094cc09455201916d016d9b2ae08ff", + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff", "shasum": "" }, "require": { "ext-xml": "*", - "php": ">=8.0.2", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/twig-bridge": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/config": "<5.4", "symfony/dependency-injection": "<5.4" }, "require-dev": { - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/web-profiler-bundle": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "For service container configuration", - "symfony/dependency-injection": "For using as a service from the container" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -11258,7 +11706,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.0.19" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.13" }, "funding": [ { @@ -11274,30 +11722,30 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.4.7", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "2088c5da700b1e7a8689fffc10dda6c1f643deea" + "reference": "b176e1f1f550ef44c94eb971bf92488de08f7c6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2088c5da700b1e7a8689fffc10dda6c1f643deea", - "reference": "2088c5da700b1e7a8689fffc10dda6c1f643deea", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b176e1f1f550ef44c94eb971bf92488de08f7c6b", + "reference": "b176e1f1f550ef44c94eb971bf92488de08f7c6b", "shasum": "" }, "require": { "masterminds/html5": "^2.6", - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "^5.4|^6.0|^7.0" + "symfony/css-selector": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -11325,7 +11773,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.7" + "source": "https://github.com/symfony/dom-crawler/tree/v7.2.0" }, "funding": [ { @@ -11341,56 +11789,55 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-13T16:15:23+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.50.0", + "version": "v1.62.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "a1733f849b999460c308e66f6392fb09b621fa86" + "reference": "0624f13b1e0ff86df6f6646c711d806d9af12629" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/a1733f849b999460c308e66f6392fb09b621fa86", - "reference": "a1733f849b999460c308e66f6392fb09b621fa86", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/0624f13b1e0ff86df6f6646c711d806d9af12629", + "reference": "0624f13b1e0ff86df6f6646c711d806d9af12629", "shasum": "" }, "require": { "doctrine/inflector": "^2.0", - "nikic/php-parser": "^4.11", - "php": ">=8.0", - "symfony/config": "^5.4.7|^6.0", - "symfony/console": "^5.4.7|^6.0", - "symfony/dependency-injection": "^5.4.7|^6.0", + "nikic/php-parser": "^4.18|^5.0", + "php": ">=8.1", + "php-cs-fixer/shim": "^v3.64", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^5.4.7|^6.0", - "symfony/finder": "^5.4.3|^6.0", - "symfony/framework-bundle": "^5.4.7|^6.0", - "symfony/http-kernel": "^5.4.7|^6.0", - "symfony/process": "^5.4.7|^6.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0" }, "conflict": { - "doctrine/doctrine-bundle": "<2.4", - "doctrine/orm": "<2.10", - "symfony/doctrine-bridge": "<5.4" + "doctrine/doctrine-bundle": "<2.10", + "doctrine/orm": "<2.15" }, "require-dev": { "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.4", - "doctrine/orm": "^2.10.0", - "symfony/http-client": "^5.4.7|^6.0", - "symfony/phpunit-bridge": "^5.4.17|^6.0", - "symfony/polyfill-php80": "^1.16.0", - "symfony/security-core": "^5.4.7|^6.0", - "symfony/yaml": "^5.4.3|^6.0", - "twig/twig": "^2.0|^3.0" + "doctrine/doctrine-bundle": "^2.5.0", + "doctrine/orm": "^2.15|^3", + "symfony/http-client": "^6.4|^7.0", + "symfony/phpunit-bridge": "^6.4.1|^7.0", + "symfony/security-core": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0", + "twig/twig": "^3.0|^4.x-dev" }, "type": "symfony-bundle", "extra": { "branch-alias": { - "dev-main": "1.0-dev" + "dev-main": "1.x-dev" } }, "autoload": { @@ -11419,7 +11866,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.50.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.62.0" }, "funding": [ { @@ -11435,20 +11882,20 @@ "type": "tidelift" } ], - "time": "2023-07-10T18:21:57+00:00" + "time": "2024-12-10T23:51:12+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.7", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "a33ca737283c76617c4089a8425c7785b344e283" + "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/a33ca737283c76617c4089a8425c7785b344e283", - "reference": "a33ca737283c76617c4089a8425c7785b344e283", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cebafe2f1ad2d1e745c1015b7c2519592341e4e6", + "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6", "shasum": "" }, "require": { @@ -11468,8 +11915,8 @@ "type": "symfony-bridge", "extra": { "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { @@ -11480,7 +11927,8 @@ "Symfony\\Bridge\\PhpUnit\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/bin/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -11500,7 +11948,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.7" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.16" }, "funding": [ { @@ -11516,42 +11964,42 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:22:46+00:00" + "time": "2024-11-13T15:06:22+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.0.19", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "326d9b572c227fa5661cdeb3bf4b938049f51bf0" + "reference": "979f8ee1a4f2464c20f3fef0d2111827fef2e97e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/326d9b572c227fa5661cdeb3bf4b938049f51bf0", - "reference": "326d9b572c227fa5661cdeb3bf4b938049f51bf0", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/979f8ee1a4f2464c20f3fef0d2111827fef2e97e", + "reference": "979f8ee1a4f2464c20f3fef0d2111827fef2e97e", "shasum": "" }, "require": { - "php": ">=8.0.2", - "symfony/config": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", + "php": ">=8.1", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", "symfony/twig-bundle": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "conflict": { - "symfony/dependency-injection": "<5.4", "symfony/form": "<5.4", "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4" + "symfony/messenger": "<5.4", + "symfony/twig-bundle": ">=7.0" }, "require-dev": { - "symfony/browser-kit": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "symfony-bundle", "autoload": { @@ -11578,8 +12026,11 @@ ], "description": "Provides a development tool that gives detailed information about the execution of any request", "homepage": "https://symfony.com", + "keywords": [ + "dev" + ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.0.19" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.17" }, "funding": [ { @@ -11595,7 +12046,7 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-12-08T23:00:41+00:00" }, { "name": "theseer/tokenizer", @@ -11654,7 +12105,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4.0 || ^8.1 || ^8.2", + "php": "^7.4.0 || ^8.1 || ^8.2 || ^8.4", "ext-ctype": "*", "ext-iconv": "*", "ext-sodium": "*" diff --git a/composer.phar b/composer.phar new file mode 100755 index 000000000..15c4a2081 Binary files /dev/null and b/composer.phar differ diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index d08ef629f..ddd60c655 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -13,10 +13,11 @@ doctrine: mappings: App: is_bundle: false - type: annotation + type: attribute dir: '%kernel.project_dir%/src/Entity' prefix: 'App\Entity' alias: App + dql: datetime_functions: date: Oro\ORM\Query\AST\Functions\SimpleFunction diff --git a/config/packages/sensio_framework_extra.yaml.bak b/config/packages/sensio_framework_extra.yaml.bak new file mode 100644 index 000000000..1821ccc07 --- /dev/null +++ b/config/packages/sensio_framework_extra.yaml.bak @@ -0,0 +1,3 @@ +sensio_framework_extra: + router: + annotations: false diff --git a/config/routes/annotations.yaml b/config/routes/annotations.yaml index e92efc596..2d2ab38a6 100644 --- a/config/routes/annotations.yaml +++ b/config/routes/annotations.yaml @@ -1,7 +1,7 @@ controllers: resource: ../../src/Controller/ - type: annotation + type: attribute kernel: resource: ../../src/Kernel.php - type: annotation + type: attribute diff --git a/docker-compose.nginx.yml b/docker-compose.nginx.yml index bb3a6fcda..71ae63bee 100644 --- a/docker-compose.nginx.yml +++ b/docker-compose.nginx.yml @@ -68,7 +68,7 @@ services: bash -c ' cd /app && yarn install && - yarn build' + yarn build --watch' volumes: web: diff --git a/package.json b/package.json index 41e82c343..b880732bc 100644 --- a/package.json +++ b/package.json @@ -81,10 +81,10 @@ "moment": "^2.29.4", "pretty": "^2.0.0", "prop-types": "^15.7.2", - "react": "^16.14.0", - "react-dom": "^16.14.0", + "react": "18.3.1", + "react-dom": "^18.3.1", "react-html-parser": "^2.0.2", - "react-router-dom": "^5.2.0", + "react-router-dom": "^6.27.0", "reactstrap": "^8.7.1" }, "resolutions": { diff --git a/src/Controller/IssuesController.php b/src/Controller/IssuesController.php index c003334ab..644f785fb 100644 --- a/src/Controller/IssuesController.php +++ b/src/Controller/IssuesController.php @@ -5,6 +5,7 @@ use App\Entity\Issue; use App\Response\ApiResponse; use App\Services\LmsPostService; +use App\Services\EqualAccessService; use App\Services\PhpAllyService; use App\Services\UtilityService; use Doctrine\Persistence\ManagerRegistry; @@ -157,13 +158,15 @@ public function markAsReviewed(Request $request, LmsPostService $lmsPost, Utilit } // Rescan an issue in PhpAlly + // TODO: implement equal access into this #[Route('/api/issues/{issue}/scan', name: 'scan_issue')] - public function scanIssue(Issue $issue, PhpAllyService $phpAlly, UtilityService $util) + public function scanIssue(Issue $issue, PhpAllyService $phpAlly, UtilityService $util, EqualAccessService $equalAccess) { $apiResponse = new ApiResponse(); $issueRule = 'CidiLabs\\PhpAlly\\Rule\\'.$issue->getScanRuleId(); $report = $phpAlly->scanHtml($issue->getHtml(), [$issueRule], $issue->getContentItem()->getCourse()->getInstitution()); + // $equalAccess->logToServer("scanIssue in issuescontroller"); $reportIssues = $report->getIssues(); $reportErrors = $report->getErrors(); diff --git a/src/Controller/SyncController.php b/src/Controller/SyncController.php index 307201d77..ed1848860 100644 --- a/src/Controller/SyncController.php +++ b/src/Controller/SyncController.php @@ -9,6 +9,8 @@ use App\Services\LmsApiService; use App\Services\LmsFetchService; use App\Services\PhpAllyService; +use App\Services\EqualAccessService; +use App\Services\ScannerService; use App\Services\UtilityService; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; @@ -125,7 +127,7 @@ public function fullCourseRescan(Course $course, LmsFetchService $lmsFetch) { } #[Route('/api/sync/content/{contentItem}', name: 'content_sync', methods: ['GET'])] - public function requestContentSync(ContentItem $contentItem, LmsFetchService $lmsFetch, PhpAllyService $phpAlly) + public function requestContentSync(ContentItem $contentItem, LmsFetchService $lmsFetch, ScannerService $scanner) { $response = new ApiResponse(); $course = $contentItem->getCourse(); @@ -135,10 +137,10 @@ public function requestContentSync(ContentItem $contentItem, LmsFetchService $lm $lmsFetch->deleteContentItemIssues(array($contentItem)); // Rescan the contentItem - $phpAllyReport = $phpAlly->scanContentItem($contentItem); + $report = $scanner->scanContentItem($contentItem, null, $this->util); // Add rescanned Issues to database - foreach ($phpAllyReport->getIssues() as $issue) { + foreach ($report->getIssues() as $issue) { // Create issue entity $lmsFetch->createIssue($issue, $contentItem); } diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index a3f2471f1..da85178da 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -22,7 +22,7 @@ class AppFixtures extends Fixture private $contentItems = []; private $issues = []; - public function load(ObjectManager $manager) + public function load(ObjectManager $manager): void { $this->manager = $manager; diff --git a/src/Entity/ContentItem.php b/src/Entity/ContentItem.php index 24e589ec1..dd5254071 100644 --- a/src/Entity/ContentItem.php +++ b/src/Entity/ContentItem.php @@ -8,73 +8,48 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass="App\Repository\ContentItemRepository") - */ +#[ORM\Entity(repositoryClass: "App\Repository\ContentItemRepository")] class ContentItem implements \JsonSerializable { // Private Members - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $title; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\Course", inversedBy="contentItems") - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\Course", inversedBy: "contentItems")] + #[ORM\JoinColumn(nullable: false)] private $course; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $contentType; - /** - * @ORM\Column(type="string", length=512) - */ + #[ORM\Column(type: "string", length: 512)] private $lmsContentId; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $updated; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $metadata; - /** - * @ORM\OneToMany(targetEntity="App\Entity\Issue", mappedBy="contentItem") - */ + #[ORM\OneToMany(targetEntity: "App\Entity\Issue", mappedBy: "contentItem")] private $issues; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: "boolean")] private $published; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: "boolean")] private $active; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $body; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $url; diff --git a/src/Entity/Course.php b/src/Entity/Course.php index 86d14c22d..187c71c8e 100644 --- a/src/Entity/Course.php +++ b/src/Entity/Course.php @@ -6,76 +6,52 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass="App\Repository\CourseRepository") - */ +#[ORM\Entity(repositoryClass: "App\Repository\CourseRepository")] class Course implements \JsonSerializable { // Private Members - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $title; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\Institution", inversedBy="courses") - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\Institution", inversedBy: "courses")] + #[ORM\JoinColumn(nullable: false)] private $institution; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + + #[ORM\Column(type: "string", length: 255, nullable: true)] private $lmsAccountId; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $lmsCourseId; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + + #[ORM\Column(type: "datetime", nullable: true)] private $lastUpdated; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $active; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $dirty; - /** - * @ORM\OneToMany(targetEntity="App\Entity\ContentItem", mappedBy="course", orphanRemoval=true) - */ + #[ORM\OneToMany(targetEntity: "App\Entity\ContentItem", mappedBy: "course", orphanRemoval: true)] + private $contentItems; - /** - * @ORM\OneToMany(targetEntity="App\Entity\Report", mappedBy="course", orphanRemoval=true) - */ + #[ORM\OneToMany(targetEntity: "App\Entity\Report", mappedBy: "course", orphanRemoval: true)] private $reports; - /** - * @ORM\OneToMany(targetEntity=FileItem::class, mappedBy="course") - */ + #[ORM\OneToMany(targetEntity: FileItem::class, mappedBy: "course")] private $fileItems; - /** - * @ORM\Column(type="integer", nullable=true) - */ + #[ORM\Column(type: "integer", nullable: true)] private $lmsTermId; - // Constructor public function __construct() { @@ -260,7 +236,7 @@ public function removeReport(Report $report): self } public function removeAllReports(): self - { + { $this->reports->clear(); return $this; } @@ -269,10 +245,10 @@ public function getPreviousReport(): ?Report { $reports = $this->reports->toArray(); $count = count($reports); - + return ($count > 1) ? $reports[$count-2] : null; } - + public function getLatestReport(): ?Report { return $this->reports->last() ?: null; @@ -314,7 +290,7 @@ public function getUpdatedReport() $report->setContentFixed($fixed); $report->setContentResolved($resolved); $report->setFilesReviewed($filesReviewed); - + return $report; } @@ -386,7 +362,7 @@ public function getAllIssues() return $allIssues; } - protected function sortContentItems(ContentItem $a, ContentItem $b) + protected function sortContentItems(ContentItem $a, ContentItem $b) { return (strtolower($a->getTitle()) > strtolower($b->getTitle())) ? 1 : -1; } diff --git a/src/Entity/FileItem.php b/src/Entity/FileItem.php index bb9c7904d..eea58fa2e 100644 --- a/src/Entity/FileItem.php +++ b/src/Entity/FileItem.php @@ -6,91 +6,58 @@ use App\Services\UtilityService; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass=FileItemRepository::class) - */ + +#[ORM\Entity(repositoryClass: FileItemRepository::class)] class FileItem implements \JsonSerializable { - /** - * @ORM\Id - * @ORM\GeneratedValue - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $fileName; - /** - * @ORM\ManyToOne(targetEntity=Course::class, inversedBy="fileItems") - */ + #[ORM\ManyToOne(targetEntity: Course::class, inversedBy: "fileItems")] private $course; - /** - * @ORM\Column(type="string", length=32) - */ + #[ORM\Column(type: "string", length: 32)] private $fileType; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $lmsFileId; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: "datetime", nullable: true)] private $updated; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $metadata; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $status; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $fileSize; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $hidden; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $reviewed; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $lmsUrl; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $downloadUrl; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + #[ORM\ManyToOne(targetEntity: User::class)] private $reviewedBy; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: "datetime", nullable: true)] private $reviewedOn; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: "boolean")] private $active; public function getId(): ?int diff --git a/src/Entity/Institution.php b/src/Entity/Institution.php index 85e50f45b..02478b52e 100644 --- a/src/Entity/Institution.php +++ b/src/Entity/Institution.php @@ -7,79 +7,54 @@ use Doctrine\ORM\Mapping as ORM; use JsonSerializable; -/** - * @ORM\Entity(repositoryClass="App\Repository\InstitutionRepository") - */ + +#[ORM\Entity(repositoryClass: "App\Repository\InstitutionRepository")] + class Institution implements JsonSerializable { // Private Members - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - /** - * @ORM\Column(type="string", length=255) - */ + + #[ORM\Column(type: "string", length: 255)] private $title; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $lmsDomain; - /** - * @ORM\Column(type="string", length=64, nullable=true) - */ + #[ORM\Column(type: "string", length: 64, nullable: true)] private $lmsId; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $lmsAccountId; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $created; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: "boolean")] private $status; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $vanityUrl; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $metadata; - /** - * @ORM\OneToMany(targetEntity="App\Entity\Course", mappedBy="institution") - */ + #[ORM\OneToMany(targetEntity: "App\Entity\Course", mappedBy: "institution")] private $courses; - /** - * @ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="institution") - */ + #[ORM\OneToMany(targetEntity: "App\Entity\User", mappedBy: "institution")] private $users; private $encodedKey = 'niLb/WbAODNi7E4ccHHa/pPU3Bd9h6z1NXmjA981D4o='; - /** - * @ORM\Column(type="string", nullable=true) - */ + #[ORM\Column(type: "string", nullable: true)] private $apiClientId; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $apiClientSecret; @@ -116,7 +91,7 @@ private function decryptData($encrypted): bool | string $decoded = base64_decode($encrypted); $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); $encrypted_text = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, NULL, '8bit'); - + return sodium_crypto_secretbox_open($encrypted_text, $nonce, $key); } diff --git a/src/Entity/Issue.php b/src/Entity/Issue.php index b8f5af2d9..c5a4dc49c 100644 --- a/src/Entity/Issue.php +++ b/src/Entity/Issue.php @@ -5,9 +5,8 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass="App\Repository\IssueRepository") - */ + +#[ORM\Entity(repositoryClass: "App\Repository\IssueRepository")] class Issue implements \JsonSerializable { static $issueError = 'error'; @@ -17,62 +16,42 @@ class Issue implements \JsonSerializable static $issueStatusResolved = 2; // Private Members - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\ContentItem", inversedBy="issues") - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\ContentItem", inversedBy: "issues")] + #[ORM\JoinColumn(nullable: false)] private $contentItem; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $scanRuleId; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $html; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $type; - /** - * @ORM\Column(type="smallint") - */ + #[ORM\Column(type: "smallint")] private $status; - /** - * @ORM\ManyToOne(targetEntity=User::class) - */ + + #[ORM\ManyToOne(targetEntity: User::class)] private $fixedBy; - /** - * @ORM\Column(type="datetime", nullable=true) - */ + #[ORM\Column(type: "datetime", nullable: true)] private $fixedOn; - /** - * @ORM\Column(type="text", nullable=true) - */ + + #[ORM\Column(type: "text", nullable: true)] private $previewHtml; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $newHtml; - /** - * @ORM\Column(type="json", nullable=true) - */ + #[ORM\Column(type: "json", nullable: true)] private $metadata; // Constructor diff --git a/src/Entity/LogEntry.php b/src/Entity/LogEntry.php index 4fcb781d5..58bc57b20 100644 --- a/src/Entity/LogEntry.php +++ b/src/Entity/LogEntry.php @@ -4,46 +4,32 @@ use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass="App\Repository\LogEntryRepository") - */ + +#[ORM\Entity(repositoryClass: "App\Repository\LogEntryRepository")] class LogEntry implements \JsonSerializable { - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] + private $id; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\User") - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\User")] private $user; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\Course") - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\Course")] private $course; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $message; - /** - * @ORM\Column(type="string", length=255) - */ + #[ORM\Column(type: "string", length: 255)] private $severity; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $created; - /** - * @ORM\Column(type="boolean", nullable=true) - */ + #[ORM\Column(type: "boolean", nullable: true)] private $status; public function getId(): ?int @@ -104,7 +90,7 @@ public function getCreated(): ?\DateTimeInterface return $this->created; } - public function setCreated(\DateTimeInterface $created = null): self + public function setCreated(?\DateTimeInterface $created = null): self { if (!$created) { $created = new \DateTime(); diff --git a/src/Entity/Report.php b/src/Entity/Report.php index de045e6f4..666c65e5d 100644 --- a/src/Entity/Report.php +++ b/src/Entity/Report.php @@ -5,69 +5,49 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; -/** - * @ORM\Entity(repositoryClass="App\Repository\ReportRepository") - */ + +#[ORM\Entity(repositoryClass: "App\Repository\ReportRepository")] class Report implements \JsonSerializable { // Private Members - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] private $id; - - /** - * @ORM\ManyToOne(targetEntity="App\Entity\Course", inversedBy="reports") - * @ORM\JoinColumn(nullable=false) - */ + + #[ORM\ManyToOne(targetEntity: "App\Entity\Course", inversedBy: "reports")] + #[ORM\JoinColumn(nullable: false)] private $course; - /** - * @ORM\Column(type="text", nullable=true) - */ + #[ORM\Column(type: "text", nullable: true)] private $data; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $created; - /** - * @ORM\Column(type="integer", nullable=true) - */ + #[ORM\Column(type: "integer", nullable: true)] private $errors; - /** - * @ORM\Column(type="integer", nullable=true) - */ + #[ORM\Column(type: "integer", nullable: true)] private $suggestions; - /** - * @ORM\Column(type="boolean") - */ + #[ORM\Column(type: "boolean")] private $ready; - /** - * @ORM\ManyToOne(targetEntity=User::class, inversedBy="reports") - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: User::class, inversedBy: "reports")] + #[ORM\JoinColumn(nullable: false)] private $author; - /** - * @ORM\Column(type="integer", nullable=true) - */ + #[ORM\Column(type: "integer", nullable: true)] + private $contentFixed; - /** - * @ORM\Column(type="integer", nullable=true) - */ + #[ORM\Column(type: "integer", nullable: true)] private $contentResolved; - /** - * @ORM\Column(type="integer", nullable=true) - */ + + #[ORM\Column(type: "integer", nullable: true)] + private $filesReviewed; // Constructor diff --git a/src/Entity/User.php b/src/Entity/User.php index eb32d01dc..c304a28cd 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -8,71 +8,52 @@ use JsonSerializable; use Symfony\Component\Security\Core\User\UserInterface; -/** - * @ORM\Entity(repositoryClass="App\Repository\UserRepository") - * @ORM\Table(name="users") - */ +#[ORM\Entity(repositoryClass: "App\Repository\UserRepository")] +#[ORM\Table(name: "users")] class User implements UserInterface, JsonSerializable { - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] + private $id; /** * $username = || - * @ORM\Column(type="string", length=180, unique=true) - */ + */ + #[ORM\Column(type: "string", length: 180, unique: true)] private string $username; - /** - * @ORM\Column(type="string", length=255, nullable=true) - */ + #[ORM\Column(type: "string", length: 255, nullable: true)] private $name; - /** - * @ORM\Column(type="json", nullable=true) - */ + #[ORM\Column(type: "json", nullable: true)] private $roles = []; - /** - * @ORM\ManyToOne(targetEntity="App\Entity\Institution", inversedBy="users") - * @ORM\JoinColumn(nullable=false) - */ + #[ORM\ManyToOne(targetEntity: "App\Entity\Institution", inversedBy: "users")] + #[ORM\JoinColumn(nullable: false)] private $institution; - /** - * @ORM\Column(type="string", length=128) - */ + #[ORM\Column(type: "string", length: 128)] private $lmsUserId; - /** - * @ORM\Column(type="string", length=2048, nullable=true) - */ + #[ORM\Column(type: "string", length: 2048, nullable: true)] private $apiKey; - /** - * @ORM\Column(type="string", length=512, nullable=true) - */ + #[ORM\Column(type: "string", length: 512, nullable: true)] private $refreshToken; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $created; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] private $lastLogin; private $encodedKey = 'niLb/WbAODNi7E4ccHHa/pPU3Bd9h6z1NXmjA981D4o='; - /** - * @ORM\OneToMany(targetEntity=Report::class, mappedBy="author") - */ + + #[ORM\OneToMany(targetEntity: Report::class, mappedBy: "author")] + private $reports; @@ -147,7 +128,7 @@ public function getSalt() /** * @see UserInterface */ - public function eraseCredentials() + public function eraseCredentials(): void { // If you store any temporary, sensitive data on the user, clear it here // $this->plainPassword = null; diff --git a/src/Entity/UserSession.php b/src/Entity/UserSession.php index 6fe9f0652..8227ccc84 100644 --- a/src/Entity/UserSession.php +++ b/src/Entity/UserSession.php @@ -6,31 +6,28 @@ use JsonSerializable; use Symfony\Component\Uid\Uuid; -/** - * @ORM\Entity(repositoryClass=UserSessionRepository::class) - */ + +#[ORM\Entity(repositoryClass: UserSessionRepository::class)] class UserSession implements JsonSerializable { - /** - * @ORM\Id - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: "integer")] + private $id; - /** - * @ORM\Column(type="string", length=255) - */ + + #[ORM\Column(type: "string", length: 255)] + private $uuid; - /** - * @ORM\Column(type="json", nullable=true) - */ + #[ORM\Column(type: "json", nullable: true)] + private $data = []; - /** - * @ORM\Column(type="datetime") - */ + #[ORM\Column(type: "datetime")] + private $created; public function getId(): ?Uuid @@ -74,7 +71,7 @@ public function set($key, $val): self return $this; } - public function has($key) + public function has($key) { return isset($this->data[$key]); } diff --git a/src/Lms/Canvas/CanvasApi.php b/src/Lms/Canvas/CanvasApi.php index 7415b049e..c644a3ba0 100644 --- a/src/Lms/Canvas/CanvasApi.php +++ b/src/Lms/Canvas/CanvasApi.php @@ -22,7 +22,7 @@ public function __construct($baseUrl, $apiToken) } // API call GET - public function apiGet(string $url, array $options = [], int $perPage = 100, LmsResponse $lmsResponse = null): LmsResponse + public function apiGet(string $url, array $options = [], int $perPage = 100, ?LmsResponse $lmsResponse = null): LmsResponse { $links = []; diff --git a/src/Lms/Canvas/CanvasLms.php b/src/Lms/Canvas/CanvasLms.php index 341d41df6..8e946d1da 100644 --- a/src/Lms/Canvas/CanvasLms.php +++ b/src/Lms/Canvas/CanvasLms.php @@ -15,7 +15,7 @@ use App\Services\SessionService; use App\Services\UtilityService; use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; class CanvasLms implements LmsInterface { /** @var ContentItemRepository $contentItemRepo */ @@ -494,7 +494,7 @@ public function getContentTypes() protected function getAccountInfo(User $user, $accountId) { - $url = "accounts/${accountId}"; + $url = "accounts/{$accountId}"; $apiDomain = $this->getApiDomain($user); $apiToken = $this->getApiToken($user); @@ -513,7 +513,7 @@ protected function getAccountInfo(User $user, $accountId) protected function getSubAccounts(User $user, $accountId) { - $url = "accounts/${accountId}/sub_accounts?recursive=true"; + $url = "accounts/{$accountId}/sub_accounts?recursive=true"; $apiDomain = $this->getApiDomain($user); $apiToken = $this->getApiToken($user); diff --git a/src/Lms/D2l/D2lLms.php b/src/Lms/D2l/D2lLms.php index 055ff5229..9fee30ef8 100644 --- a/src/Lms/D2l/D2lLms.php +++ b/src/Lms/D2l/D2lLms.php @@ -15,7 +15,7 @@ use App\Services\SessionService; use App\Services\UtilityService; use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Security\Core\Security; +use Symfony\Bundle\SecurityBundle\Security; class D2lLms implements LmsInterface { diff --git a/src/Security/SessionAuthenticator.php b/src/Security/SessionAuthenticator.php index f7e3a11a5..64534a886 100644 --- a/src/Security/SessionAuthenticator.php +++ b/src/Security/SessionAuthenticator.php @@ -57,7 +57,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio return null; } - public function start(Request $request, AuthenticationException $exception = null) + public function start(Request $request, ?AuthenticationException $exception = null) { return new Response('authentication failed'); } diff --git a/src/Services/AsyncEqualAccessReport.php b/src/Services/AsyncEqualAccessReport.php new file mode 100644 index 000000000..9964a1835 --- /dev/null +++ b/src/Services/AsyncEqualAccessReport.php @@ -0,0 +1,247 @@ +loadConfig(); + } + + private function loadConfig() { + // Load variables for AWS + $this->awsAccessKeyId = $_ENV['EQUALACCESS_AWS_ACCESS_KEY_ID']; + $this->awsSecretAccessKey = $_ENV['EQUALACCESS_AWS_SECRET_ACCESS_KEY']; + $this->awsRegion = $_ENV['EQUALACCESS_AWS_REGION']; + $this->host = $_ENV['EQUALACCESS_AWS_HOST']; + $this->canonicalUri = $_ENV['EQUALACCESS_AWS_CANONICAL_URI']; + $this->endpoint = "https://{$this->host}/{$this->canonicalUri}"; + } + + public function logToServer(string $message) { + $options = [ + 'http' => [ + 'header' => "Content-type: text/html\r\n", + 'method' => 'POST', + 'content' => $message, + ], + ]; + + $context = stream_context_create($options); + file_get_contents("http://host.docker.internal:3000/log", false, $context); + } + + public function sign(RequestInterface $request): RequestInterface { + $signature = new SignatureV4('execute-api', $this->awsRegion); + $credentials = new Credentials($this->awsAccessKeyId, $this->awsSecretAccessKey); + + return $signature->signRequest($request, $credentials); + } + + public function createRequest($payload) { + return new Request( + "POST", + "{$this->endpoint}", + [ + "Content-Type" => "application/json", + ], + $payload, + ); + } + + public function postMultipleArrayAsync(array $contentItems): array { + $promises = []; + $contentItemsReport = []; + + $client = new Client(); + + // Combine every pages into a request + $htmlArray = []; + $counter = 0; + $payloadSize = 5; + foreach ($contentItems as $contentItem) { + if ($counter >= $payloadSize) { + // Reached our counter limit, create a new payload + // and create and sign a request that we send to the lambda function + $payload = json_encode(["html" => $htmlArray]); + + $request = $this->createRequest($payload); + $signedRequest = $this->sign($request); + + $promises[] = $client->sendAsync($signedRequest); + $counter = 0; + + $htmlArray = []; + } + + // Get the HTML then clean up and push a page into an array + $html = $contentItem->getBody(); + $document = $this->getDomDocument($html)->saveHTML(); + array_push($htmlArray, $document); + + $counter++; + } + + // Send out any leftover pages we might have + if (count($htmlArray) > 0) { + $payload = json_encode(["html" => $htmlArray]); + + $request = $this->createRequest($payload); + $signedRequest = $this->sign($request); + + $promises[] = $client->sendAsync($signedRequest); + } + + // $this->logToServer("Number of promises:"); + // $this->logToServer(count($promises)); + + $results = Promise\Utils::settle($promises)->wait(); + // $results = Promise\Utils::unwrap($promises); + + $errors = 0; + + foreach ($results as $result) { + // Every "block" of reports pages should be in a stringified + // JSON, so we need to decode the JSON to be able to iterate through + // it first.} + + if (isset($result["value"])) { + $response = json_decode($result["value"]->getBody()->getContents(), true); + } + else if (isset($result["reason"])) { + $errors++; + } + + // $this->logToServer($result["value"]->getBody()->getContents()); + + foreach ($response as $report) { + // $this->logToServer(json_encode($report)); + $contentItemsReport[] = $report; + } + } + + // $this->logToServer("Number of errors:"); + // $this->logToServer($errors); + + return $contentItemsReport; + } + + + public function postMultipleAsync(array $contentItems): array { + $promises = []; + + $client = new Client(); + + // Iterate through each scannable Canvas page and add a new + // POST request to our array of promises + foreach ($contentItems as $contentItem) { + // $this->logToServer("Checking: {$contentItem->getTitle()}"); + // Clean up the content item's HTML document + // then create a payload that we'll send to the lambda function + $html = $contentItem->getBody(); + $document = $this->getDomDocument($html)->saveHTML(); + + $payload = json_encode(["html" => $document]); + $request = $this->createRequest($payload); + $signedRequest = $this->sign($request); + + $promises[] = $client->sendAsync($signedRequest); + } + + // Wait for all the POSTs to resolve and save them into an array + // Each promise is resolved into an array with a "state" key (fulfilled/rejected) and "value" (the JSON) + $results = Promise\Utils::unwrap($promises); + + // Save the report for the content item into an array. + // They should (in theory) be in the same order they were sent in. + foreach ($results as $result) { + $response = $result->getBody()->getContents(); + $json = json_decode($response, true); + // $this->logToServer(json_encode($json, JSON_PRETTY_PRINT)); + // $this->logToServer("Saving to contentItemsReport..."); + $contentItemsReport[] = $json; + } + + return $contentItemsReport; + } + + // Scan a single content item + public function postSingleAsync(ContentItem $contentItem) { + $client = new Client(); + $report = null; + + // Clean up the content item's HTML document + // and create a payload to send + $html = $contentItem->getBody(); + $document = $this->getDomDocument($html)->saveHTML(); + $payload = json_encode(["html" => $document]); + + $request = $this->createRequest($payload); + $signedRequest = $this->sign($request); + + // POST document to Lambda and wait for fulfillment + // $this->logToServer("Sending to single promise..."); + $promise = $client->sendAsync($signedRequest); + $response = $promise->wait(); + + if ($response) { + // $this->logToServer("Fulfilled!"); + + $contents = $response->getBody()->getContents(); + $report = json_decode($contents, true)[0]; + } + + // Return the Equal Access report + return $report; + } + + public function getDomDocument($html) + { + // Load the HTML string into a DOMDocument that PHP can parse. + // TODO: checks for if , , or and