(本文最初由Torque Magazine發(fā)表,經(jīng)許可轉(zhuǎn)載。)
近年來,筆者在Torque雜志上撰寫了大量關(guān)于面向?qū)ο驪HP和WordPress REST API的文章,也涉及到使用Composer進(jìn)行依賴管理和自動加載,以及單元測試。所有文章的核心觀點是:通過將已建立的軟件開發(fā)最佳實踐應(yīng)用到WordPress開發(fā)中,我們可以創(chuàng)建更好的插件。
這是一系列文章中的第一篇,它將在一個實際的、功能性的示例中整合這些概念。我將逐步講解如何創(chuàng)建一個WordPress插件來修改WordPress REST API端點的功能,以便更好地優(yōu)化搜索。該插件可在GitHub上找到。您可能需要瀏覽提交日志以了解我的構(gòu)建過程。
在本系列文章中,我將介紹如何使用現(xiàn)代面向?qū)ο驪HP構(gòu)建插件和類,以及如何使其可測試,以及如何為其編寫自動化測試。我將介紹單元測試、集成測試和驗收測試之間的區(qū)別,并向您展示如何編寫和自動化運行每種類型的測試。本文首先介紹如何使用面向?qū)ο蟮姆椒ㄊ褂眠^濾器修改WordPress REST API。
關(guān)鍵要點
- 利用面向?qū)ο驪HP增強WordPress REST API端點,從而實現(xiàn)更好的搜索功能,并與ElasticSearch等高級搜索工具集成。
- 修改REST API端點參數(shù)和WP_Query交互,繞過默認(rèn)WordPress搜索的限制,提高復(fù)雜查詢的響應(yīng)質(zhì)量。
- 為健壯且易于維護(hù)的代碼實現(xiàn)單元測試、集成測試和驗收測試,確保每個組件在WordPress生態(tài)系統(tǒng)中都能正確運行。
- 使用依賴注入和PHP Traits來干凈地管理類依賴關(guān)系,從而實現(xiàn)更易于維護(hù)和測試的代碼。
- 自定義REST API端點模式以包含其他參數(shù),例如
post_type
,從而實現(xiàn)更靈活和強大的搜索功能。 - 通過特定的REST API請求動態(tài)調(diào)整WP_Query參數(shù),利用過濾器有效地細(xì)化搜索結(jié)果和端點行為。
使用REST API改進(jìn)WordPress搜索
通常使用SearchWP或Relevansi之類的插件,或與ElasticSearch(一種使用與WordPress完全不同的堆棧的技術(shù))集成(使用Jetpack或ElasticPress),來改進(jìn)WordPress搜索。這些類型的插件提供更好的搜索結(jié)果,并且通常與多方面搜索界面配合使用,這對于電子商務(wù)應(yīng)用程序非常有用。
通過WordPress REST API進(jìn)行搜索繼承了所有這些相同的問題和相同的解決方案。在這篇文章中,我將首先介紹搜索的默認(rèn)工作方式以及其局限性。然后,我們將研究如何使用兩種不同的方法修改搜索并與SearchWP集成。
WordPress內(nèi)置的搜索功能通常需要使用外部服務(wù)來改進(jìn)。雖然本文是關(guān)于修改WordPress REST API帖子路由工作方式的面向?qū)ο蠓椒?,但實際示例將是改進(jìn)搜索。
當(dāng)WordPress用作解耦前端(例如原生移動應(yīng)用程序或Web應(yīng)用程序,可能使用Vue、React或Angular構(gòu)建)的后端時,通過REST API進(jìn)行高質(zhì)量搜索非常重要。本文介紹的代碼將有助于您,如果您的應(yīng)用程序用戶需要查找正確的產(chǎn)品變體或根據(jù)基于多個分類法的復(fù)雜算法搜索內(nèi)容,并且您正在編寫自定義代碼,而不僅僅是安裝插件。
使用WordPress REST API搜索帖子
如果您想在一個站點上搜索所有帖子類型為“product”的帖子,使用搜索詞“Taco Shirts”,您將向/wp/v2/product?s=Taco Shirt
端點發(fā)出請求。如果您想提高結(jié)果的質(zhì)量,上面列出的解決方案將有所幫助。
如上所述,WP_Query(WordPress REST API的帖子端點使用的東西)并不是一個很好的搜索工具。更具體地說,WP_Query可能由于其對MySQL的依賴性,不如那些傾向于使用NoSQL數(shù)據(jù)庫構(gòu)建的專用搜索工具。
首先,讓我們看看如何在進(jìn)行REST API請求時繞過WP_Query與WordPress數(shù)據(jù)庫的交互。
這是許多搜索插件用來替換其自身搜索系統(tǒng)結(jié)果(對于WP_Query默認(rèn)生成的)的策略。搜索系統(tǒng)可以使用相同的數(shù)據(jù)庫。它也可以連接到其他數(shù)據(jù)庫,可能通過API請求,例如到ElasticSearch或Apache Solr服務(wù)器。
如果您查看WordPress核心代碼,您會發(fā)現(xiàn)過濾器“posts_pre_query”在WP_Query查詢數(shù)據(jù)庫之前運行,但在SQL查詢準(zhǔn)備之后運行。此過濾器默認(rèn)返回null。如果該值為null,WordPress將繼續(xù)其默認(rèn)行為:查詢WordPress數(shù)據(jù)庫并將結(jié)果作為簡單的WP_Post對象數(shù)組返回。
另一方面,如果此過濾器的返回值是一個數(shù)組(希望包含WP_Post對象),則不使用WordPress的默認(rèn)行為。
讓我們看看如何使用posts_pre_query返回一個模擬WP_Post。此策略對于測試非常有用,但相同模式的更復(fù)雜版本可用于將單獨的數(shù)據(jù)庫與您的WordPress站點集成:
// ... (代碼示例與原文相同) ...
在此示例中,我們使用的是模擬數(shù)據(jù),但我們可以使用SearchWP的查詢類或其他任何東西。關(guān)于這段代碼需要注意的另一件事是,它將在任何WP_Query上運行,而不僅僅是WordPress REST API創(chuàng)建的WP_Query對象。讓我們對其進(jìn)行修改,以便除非它是WordPress REST API請求,否則我們不使用過濾器:
// ... (代碼示例與原文相同) ...
修改WordPress REST API端點參數(shù)
我們剛剛研究了如何更改WordPress REST API請求的搜索結(jié)果生成方式。這允許我們優(yōu)化查詢以獲得更好的搜索效果,但它可能會暴露出對端點不同模式的需求。
例如,如果您希望允許對產(chǎn)品端點的搜索可選地允許將其他帖子類型包含在搜索中,我去年介紹了另一種解決同一問題的方法。
橫切關(guān)注點
我們即將研究如何修改允許的端點參數(shù)以及如何使用它們來創(chuàng)建WP_Query參數(shù)。這是兩個單獨的關(guān)注點,單一職責(zé)原則指出我們需要為每個關(guān)注點創(chuàng)建一個類。但是這兩個類將具有共享的關(guān)注點。
例如,如果我們想允許按不同的帖子類型進(jìn)行查詢,我們需要知道哪些是公共帖子類型,以及它們的slug和rest_base參數(shù)是什么。所有這些信息都可以從函數(shù)get_post_types中獲得。
該函數(shù)的輸出并不完全是我們需要的。因此,讓我們設(shè)計一個類來根據(jù)我剛才列出的需求格式化數(shù)據(jù),并為我們提供訪問它的輔助方法。
將其視為所有我們需要在可用容器中使用的帖子類型數(shù)據(jù)的通用形狀:
// ... (代碼示例與原文相同) ...
請注意,我們沒有在類中調(diào)用get_post_types(),而是將其用作依賴項,通過構(gòu)造函數(shù)注入。因此,此類可以在不加載WordPress的情況下進(jìn)行測試。
這就是為什么我會將此類描述為“單元可測試”的原因。它不依賴于任何其他API,我們也不擔(dān)心副作用。我們可以將其作為一個單獨的、隔離的單元進(jìn)行測試。將關(guān)注點分離并將其功能隔離成小的部分,一旦我們有了單元測試覆蓋率,就可以使代碼易于維護(hù)。我將在我的下一篇文章中介紹如何測試這種類型的類。
請記住,此類確實依賴于WP_Post_Type。我的單元測試將沒有定義該類,因為只有集成測試才可以使用WordPress或任何其他外部依賴項。該類僅用于表示數(shù)據(jù),而不是執(zhí)行任何操作。因此,我們可以說它的使用不會產(chǎn)生任何副作用。因此,我很樂意在單元測試中使用模擬來代替真實的WP_Post_Type。
說到依賴注入,那些需要此新類的對象的類,我們想遵循相同的模式。我們不會在需要它們的類中實例化PreparedPostTypes,而是傳入一個實例。這意味著使用PreparedPostTypes和PreparedPostType的類保持隔離,并且可以單獨測試。
它還可以導(dǎo)致代碼重用,因為我們必須使依賴注入成為可能,并為此對象設(shè)置一個屬性。我們可以使用剪切和粘貼,或者我們可以使用PHP Trait,這是一種更高級、更可擴(kuò)展的方法,用于在類之間復(fù)制方法和屬性。
這是一個Trait,它建立了將PreparedPostTypes對象注入其他類的模式:
// ... (代碼示例與原文相同) ...
我們的另一個關(guān)注點是,我們需要在多個地方了解帖子類型的一些信息。例如帖子類型的slug。這與之前的橫切關(guān)注點略有不同。我們解決的最后一個問題涉及動態(tài)數(shù)據(jù)?,F(xiàn)在我們只需要在一個地方更改我們在多個地方使用的字符串即可。
一個具有類常量的類為我們簡單地解決了這個問題:
// ... (代碼示例與原文相同) ...
現(xiàn)在我們可以使這些字符串在整個代碼中保持一致。這似乎是不必要的步驟。但是我的示例代碼適用于帖子帖子類型。如果您想更改使用的帖子類型,則此類需要更改,而無需更改其他任何內(nèi)容。這是遵循Tom McFarlin在他撰寫“一個類應(yīng)該只有一個更改原因”時對單一職責(zé)原則的首選定義。
修改REST API端點模式
現(xiàn)在我們需要修改帖子類型端點的模式。通過這樣做,WordPress將向REST API端點傳達(dá)帖子類型參數(shù)是允許的,并且在解析請求時,允許新的端點參數(shù)。
這是我們的類,用于添加post_type屬性。請注意,它使用了我們剛才討論過的trait UsesPreparedPostTypes:
// ... (代碼示例與原文相同) ...
在此屬性的設(shè)置中,我們告訴WordPress此屬性是一個數(shù)組屬性,我們使用數(shù)組的“enum”索引指定允許的值。
在“enum”中,我們枚舉允許的值。在這種情況下,PreparedPostTypes類提供了允許值的數(shù)組,因為這是一個先前解決的橫切關(guān)注點。
請注意,此類沒有與任何帖子類型甚至此特定用例耦合。我們將很快回到使用哪些鉤子來使此類適用于特定帖子類型。
修改REST API WP_Query參數(shù)
上一節(jié)介紹了如何使新的端點屬性post_type可用。這實際上并沒有更改WordPress REST API生成的WP_Query參數(shù)。除了最后一個過濾器之外,我們已經(jīng)擁有所需的一切。
帖子類型是核心代碼專門不允許通過REST API請求更改的一個WP_Query參數(shù)。我們有一個動態(tài)命名的過濾器——rest_{$post_type}_query——可以覆蓋任何WP_Query參數(shù)。
這是我們的類,它注入我們的post_type參數(shù),這些參數(shù)以前是不允許的:
// ... (代碼示例與原文相同) ...
大部分內(nèi)容只是驗證我們是否應(yīng)該進(jìn)行更改,然后使用WP_Rest_Request的get_param方法從請求中獲取值。大部分是自動的,因為我們首先修改模式以匹配。
修改WordPress REST API請求的WP_Query對象
我已經(jīng)在本文的第一部分介紹了如何做到這一點。這是一個實現(xiàn)相同模式的類:
// ... (代碼示例與原文相同) ...
我希望您注意到這段代碼與WordPress緊密相關(guān),并且不可測試。它使用來自WordPress的WP_Post,它正在檢查WordPress的常量,并與WordPress的插件API交互。我們可以模擬WP_Post,并且我們可以自己設(shè)置常量。但是插件的API——這是需要測試的重要功能。在我的接下來的幾篇文章中,我將介紹如何重構(gòu)此類,以便我們可以使用單元測試來涵蓋除刪除該過濾器的效果之外的所有內(nèi)容,并使用集成測試來檢查該效果。
我選擇使用靜態(tài)方法有兩個原因。首先,它使在多個位置添加和刪除它變得很容易。例如,在ModifyQuery類中,我只在需要時才掛鉤此過濾器:
// ... (代碼示例與原文相同) ...
此外,在使用此過濾器時很容易創(chuàng)建遞歸循環(huán)。能夠像在此示例代碼中一樣輕松地刪除它非常不錯。
我選擇使用靜態(tài)方法的另一個原因是該函數(shù)與其他API交互。它永遠(yuǎn)不會真正可進(jìn)行單元測試。這種模式,一個具有靜態(tài)方法的類,使得在集成測試中模擬該類變得非常容易,從而最大限度地減少了在這個系統(tǒng)的一個部分中缺乏強隔離的影響。
使所有內(nèi)容協(xié)同工作
到目前為止,我們看到的代碼與WordPress非常脫鉤。這有很多好處。但這意味著它本身什么也不做。這很好。我們到目前為止只處理了業(yè)務(wù)邏輯需求?,F(xiàn)在我們需要考慮集成。
這并不難,只需要添加一些鉤子即可。哪些鉤子?與我們?yōu)镸odifyQuery和ModifySchema類設(shè)計的完全相同的兩個鉤子。對解耦業(yè)務(wù)邏輯的渴望并不意味著我們在設(shè)計其公共接口時不能考慮編寫代碼的實際原因。否則,我們只會毫無理由地為我們的代碼增加額外的復(fù)雜性。
一般來說,我盡量只在它使生活更輕松時才增加軟件復(fù)雜性。我過去偏離了這條道路。我們都有過,沒關(guān)系,練習(xí)寬恕。
我們即將掛鉤的類中的方法與鉤子使用完全相同的參數(shù)和返回類型。它們的工作是將這些值分派給其他組件。
// ... (代碼示例與原文相同) ...
下一步:測試
這已經(jīng)足夠接近了。它會起作用。由于缺乏添加鉤子的正式系統(tǒng),這是我們可以為初始化做的最好的事情。這很好。我將在未來關(guān)于WordPress集成測試的文章中介紹如何創(chuàng)建一個更復(fù)雜和可擴(kuò)展的引導(dǎo)過程。
在這篇文章中,我們研究了創(chuàng)建代碼來修改模式、WP_Query參數(shù)生成和帖子類型的底層WP_Query。我鼓勵您將此代碼轉(zhuǎn)換為插件,使用Composer進(jìn)行自動加載。在我的下一篇文章中,我們將研究單元測試以涵蓋這些類。
(以下為原文FAQ部分,已根據(jù)原文內(nèi)容進(jìn)行偽原創(chuàng))
關(guān)于WordPress中高級OOP和自定義REST API端點的常見問題解答
面向?qū)ο缶幊?OOP)在WordPress中的意義是什么?
面向?qū)ο缶幊?OOP)是一種使用“對象”設(shè)計應(yīng)用程序和軟件的編程范式。在WordPress環(huán)境中,OOP為開發(fā)復(fù)雜的應(yīng)用程序提供了一種簡潔、高效和健壯的方法。它允許開發(fā)人員將相關(guān)任務(wù)分組到類和對象中,使代碼更易于閱讀、重用和維護(hù)。OOP還通過封裝數(shù)據(jù)并防止外部直接訪問來增強應(yīng)用程序的安全性。
如何在WordPress中自定義REST API端點?
WordPress REST API提供了一組用于不同類型數(shù)據(jù)的默認(rèn)端點。但是,您可以自定義這些端點或創(chuàng)建新的端點以滿足您的特定需求。這可以通過在您的插件或主題中使用register_rest_route()
函數(shù)來完成。此函數(shù)允許您指定端點的路由或URL,并定義它應(yīng)該響應(yīng)的方法(GET、POST等)。
自定義WordPress REST API端點的優(yōu)勢是什么?
自定義WordPress REST API端點允許您創(chuàng)建更高效、更靈活和更安全的應(yīng)用程序。您可以調(diào)整端點返回的數(shù)據(jù),減少通過網(wǎng)絡(luò)發(fā)送的不必要數(shù)據(jù)量。您還可以創(chuàng)建執(zhí)行特定任務(wù)的端點,例如處理表單提交或生成報告,從而使您的應(yīng)用程序更具交互性和用戶友好性。
OOP如何增強WordPress應(yīng)用程序的安全性?
OOP通過將數(shù)據(jù)和方法封裝在對象中來增強WordPress應(yīng)用程序的安全性。這意味著對象的屬性(數(shù)據(jù))和方法(函數(shù))對應(yīng)用程序的其余部分隱藏,并且只能通過對象的方法訪問。這可以防止未經(jīng)授權(quán)訪問和操作數(shù)據(jù),從而降低安全漏洞的風(fēng)險。
OOP可以與舊版本的WordPress一起使用嗎?
是的,您可以將OOP與舊版本的WordPress一起使用。但是,需要注意的是,較新版本的WordPress對OOP的支持有所改進(jìn),并且包含許多功能,使使用此范式進(jìn)行開發(fā)更容易。因此,雖然可以使用OOP與舊版本一起使用,但通常建議使用最新版本的WordPress以獲得最佳的開發(fā)體驗。
類和對象在OOP中的作用是什么?
在OOP中,類是創(chuàng)建對象的藍(lán)圖或模板。它定義了對象應(yīng)該具有的屬性(數(shù)據(jù))和方法(函數(shù))。另一方面,對象是類的實例。它具有自己的一組屬性和方法,這些屬性和方法可能與同一類的其他對象不同。類和對象的使用使代碼更具組織性、可重用性和易于維護(hù)性。
如何在WordPress中創(chuàng)建一個新類?
您可以使用class
關(guān)鍵字,后跟類名和一組花括號{}
來在WordPress中創(chuàng)建一個新類。在括號內(nèi),您可以定義類的屬性和方法。要創(chuàng)建類的對象,您可以使用new
關(guān)鍵字,后跟類名。
WordPress中的REST API是什么?
WordPress中的REST API是一個接口,允許您使用HTTP請求與WordPress站點交互。它為不同類型的數(shù)據(jù)(例如帖子、評論和用戶)提供了一組端點,您可以使用標(biāo)準(zhǔn)HTTP方法(如GET、POST、PUT和DELETE)來訪問這些端點。REST API使您可以更輕松地從外部應(yīng)用程序創(chuàng)建、讀取、更新和刪除WordPress站點中的數(shù)據(jù)。
如何在WordPress中訪問REST API?
您可以通過向相應(yīng)的端點發(fā)送HTTP請求來訪問WordPress中的REST API。每個端點對應(yīng)于特定類型的數(shù)據(jù),并支持某些HTTP方法。例如,要檢索帖子列表,您可以向/wp/v2/posts
端點發(fā)送GET請求。REST API將以JSON格式返回數(shù)據(jù),然后您可以在應(yīng)用程序中處理和顯示這些數(shù)據(jù)。
我可以將REST API與非WordPress應(yīng)用程序一起使用嗎?
是的,您可以將REST API與非WordPress應(yīng)用程序一起使用。REST API是平臺無關(guān)的,這意味著它可以與任何可以發(fā)送HTTP請求和處理JSON數(shù)據(jù)的應(yīng)用程序一起使用。這使其成為將WordPress站點與其他應(yīng)用程序(例如移動應(yīng)用程序、桌面應(yīng)用程序和其他Web服務(wù))集成的強大工具。
以上是WordPress的高級OOP:自定義REST API端點的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機

Video Face Swap
使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級代碼編輯軟件(SublimeText3)

使用Git管理WordPress項目時,應(yīng)只將主題、自定義插件和配置文件納入版本控制;設(shè)置.gitignore文件以忽略上傳目錄、緩存和敏感配置;利用webhook或CI工具實現(xiàn)自動部署并注意數(shù)據(jù)庫處理;采用兩分支策略(main/develop)進(jìn)行協(xié)作開發(fā)。這樣做可避免沖突、保障安全,并提升協(xié)作與部署效率。

創(chuàng)建Gutenberg塊的關(guān)鍵在于理解其基本結(jié)構(gòu)并正確連接前后端資源。1.準(zhǔn)備開發(fā)環(huán)境:安裝本地WordPress、Node.js和@wordpress/scripts;2.使用PHP注冊塊并用JavaScript定義塊的編輯和顯示邏輯;3.通過npm構(gòu)建JS文件以使更改生效;4.遇到問題時檢查路徑、圖標(biāo)是否正確或使用實時監(jiān)聽構(gòu)建避免重復(fù)手動編譯。按照這些步驟,可以逐步實現(xiàn)一個簡單的Gutenberg塊。

使用WordPress測試環(huán)境是為了確保新功能、插件或主題在正式上線前的安全性和兼容性,避免影響真實網(wǎng)站。搭建測試環(huán)境的步驟包括:下載安裝本地服務(wù)器軟件(如LocalWP、XAMPP),創(chuàng)建站點、設(shè)置數(shù)據(jù)庫和管理員賬號,安裝主題和插件進(jìn)行測試;復(fù)制正式網(wǎng)站到測試環(huán)境的方法是通過插件導(dǎo)出站點、導(dǎo)入測試環(huán)境并替換域名;使用時應(yīng)注意不使用真實用戶數(shù)據(jù)、定期清理無用數(shù)據(jù)、備份測試狀態(tài)、適時重置環(huán)境,并統(tǒng)一團(tuán)隊配置以減少差異問題。

在WordPress中,當(dāng)新增自定義文章類型或修改固定鏈接結(jié)構(gòu)后,需手動刷新重寫規(guī)則,此時可通過代碼調(diào)用flush_rewrite_rules()函數(shù)實現(xiàn)。1.可在主題或插件激活鉤子中添加該函數(shù)以自動刷新;2.僅在必要時執(zhí)行一次,如添加CPT、分類法或修改鏈接結(jié)構(gòu)后;3.避免頻繁調(diào)用以免影響性能;4.多站點環(huán)境下需視情況為每個站點單獨刷新;5.某些托管環(huán)境可能限制規(guī)則保存。此外,訪問“設(shè)置>固定鏈接”頁面點擊保存也可觸發(fā)刷新,適合非自動化場景。

tosetupredirectsinwordpressingthe.htaccessfile,locateThEfileInyourSite'sRootDirectorectoryAndDrectRectrulesabovethe#beginWordPresssection.forbasic301redirects,USETHEETHEETERECTREFTATRECTATREDERTREFTATREDERTREFTATRECTRECTATRECTRECTATREDECT301/OLD-PAGEHTTPS:

UsingsMtpForWordPresseMailSimProvesDeliverabilitialComparedComparedTothEdeDefaultPhpMail()函數(shù).1.smtpauthenticateswithyouremailserver.2.somemomehostsdisablesablephpmail()

要實現(xiàn)響應(yīng)式WordPress主題設(shè)計,首先要使用HTML5和移動優(yōu)先的Meta標(biāo)簽,在header.php中添加viewport設(shè)置以確保移動端正確顯示,并用HTML5結(jié)構(gòu)標(biāo)簽組織布局;其次,利用CSS媒體查詢實現(xiàn)不同屏幕寬度下的樣式適配,按移動優(yōu)先原則編寫樣式,常用斷點包括480px、768px和1024px;第三,彈性處理圖片和布局,為圖片設(shè)置max-width:100%并使用Flexbox或Grid布局替代固定寬度;最后,通過瀏覽器開發(fā)者工具和真實設(shè)備進(jìn)行充分測試,優(yōu)化加載性能,確保響應(yīng)

TOINTEGRATETHIRD-PARTYAPISINTOWORDPRESS,關(guān)注臺詞:1.SelectAutableabepianDobtainCredentialslikeapikeYsoroAuthtoKensByEnterRegisteringThemSecure.2.ChooseBeteBetB??eteBetB??eteBetB??etebetInpliCityOorcustimplicityOrcustomPliCoseTompliCoseTomploomcoseusionfunctionfunctionfunctibunitiacuciencipuity forfunigation。
